home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / Mpeg.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  66.0 KB  |  2,658 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "VirtualDub.h"
  19. #include <stdio.h>
  20. #include <crtdbg.h>
  21. #include <process.h>
  22. #include <windows.h>
  23. #include <commctrl.h>
  24. #include <fcntl.h>
  25. #include <io.h>
  26.  
  27. #include "AudioSource.h"
  28. #include "VideoSource.h"
  29. #include "FastReadStream.h"
  30. #include "Error.h"
  31.  
  32. #include "misc.h"
  33. #include "mpeg.h"
  34. #include "mpeg_decode.h"
  35. #include "resource.h"
  36. #include "gui.h"
  37. #include "cpuaccel.h"
  38.  
  39. #include "IAMPDecoder.h"
  40.  
  41. //////////////////////////////////////////////////////////////////////////
  42.  
  43. extern HINSTANCE g_hInst;
  44. extern char g_msgBuf[128];
  45.  
  46. //////////////////////////////////////////////////////////////////////////
  47.  
  48. #define ENABLE_AUDIO_SUPPORT
  49.  
  50. #define VIDPKT_TYPE_SEQUENCE_START        (0xb3)
  51. #define    VIDPKT_TYPE_SEQUENCE_END        (0xb7)
  52. #define VIDPKT_TYPE_GROUP_START            (0xb8)
  53. #define VIDPKT_TYPE_PICTURE_START        (0x00)
  54. #define VIDPKT_TYPE_SLICE_START_MIN        (0x01)
  55. #define    VIDPKT_TYPE_SLICE_START_MAX        (0xaf)
  56. #define VIDPKT_TYPE_EXT_START            (0xb5)
  57. #define VIDPKT_TYPE_USER_START            (0xb2)
  58.  
  59. //////////////////////////////////////////////////////////////////////////
  60. //
  61. //
  62. //                            DataVector
  63. //
  64. //
  65. //////////////////////////////////////////////////////////////////////////
  66.  
  67. class DataVectorBlock {
  68. public:
  69.     enum { BLOCK_SIZE = 4096 };
  70.  
  71.     DataVectorBlock *next;
  72.  
  73.     char heap[BLOCK_SIZE];
  74.     int index;
  75.  
  76.     DataVectorBlock() {
  77.         next = NULL;
  78.         index = 0;
  79.     }
  80. };
  81.  
  82. class DataVector {
  83. private:
  84.     DataVectorBlock *first, *last;
  85.     int item_size;
  86.     int count;
  87.  
  88.     void _Add(void *);
  89.  
  90. public:
  91.     DataVector(int item_size);
  92.     ~DataVector();
  93.  
  94.     void Add(void *pp) {
  95.         if (!last || last->index >= DataVectorBlock::BLOCK_SIZE - item_size) {
  96.             _Add(pp);
  97.             return;
  98.         }
  99.  
  100.         memcpy(last->heap + last->index, pp, item_size);
  101.         last->index += item_size;
  102.         ++count;
  103.     }
  104.  
  105.     void *MakeArray();
  106.  
  107.     int Length() { return count; }
  108. };
  109.  
  110. DataVector::DataVector(int _item_size) : item_size(_item_size) {
  111.     first = last = NULL;
  112.     count = 0;
  113. }
  114.  
  115. DataVector::~DataVector() {
  116.     DataVectorBlock *i, *j;
  117.  
  118.     j = first;
  119.     while(i=j) {
  120.         j = i->next;
  121.         delete i;
  122.     }
  123. }
  124.  
  125. void DataVector::_Add(void *pp) {
  126.     if (!last || last->index > DataVectorBlock::BLOCK_SIZE - item_size) {
  127.         DataVectorBlock *ib = new DataVectorBlock();
  128.  
  129.         if (!ib) throw MyMemoryError();
  130.  
  131.         if (last)        last->next = ib;
  132.         else            first = ib;
  133.  
  134.         last = ib;
  135.     }
  136.  
  137.     memcpy(last->heap + last->index, pp, item_size);
  138.     last->index += item_size;
  139.     ++count;
  140. }
  141.  
  142. void *DataVector::MakeArray() {
  143.     char *array = new char[count * item_size], *ptr = array;
  144.     DataVectorBlock *dvb = first;
  145.  
  146.     if (!array) throw MyMemoryError();
  147.  
  148.     while(dvb) {
  149.         memcpy(ptr, dvb->heap, dvb->index);
  150.         ptr += dvb->index;
  151.  
  152.         dvb=dvb->next;
  153.     }
  154.  
  155.     return array;
  156. }
  157.  
  158.  
  159.  
  160. //////////////////////////////////////////////////////////////////////////
  161. //
  162. //
  163. //                    InputFileMPEGOptions
  164. //
  165. //
  166. //////////////////////////////////////////////////////////////////////////
  167.  
  168. class InputFileMPEGOptions : public InputFileOptions {
  169. public:
  170.     enum {
  171.         DECODE_NO_B    = 1,
  172.         DECODE_NO_P    = 2,
  173.     };
  174.  
  175.     struct InputFileMPEGOpts {
  176.         int len;
  177.         int iDecodeMode;
  178.         bool fAcceptPartial;
  179.     } opts;
  180.  
  181.         
  182.     ~InputFileMPEGOptions();
  183.  
  184.     bool read(const char *buf);
  185.     int write(char *buf, int buflen);
  186.  
  187.     static BOOL APIENTRY SetupDlgProc( HWND hDlg, UINT message, UINT wParam, LONG lParam);
  188. };
  189.  
  190. InputFileMPEGOptions::~InputFileMPEGOptions() {
  191. }
  192.  
  193. bool InputFileMPEGOptions::read(const char *buf) {
  194.     const InputFileMPEGOpts *pp = (const InputFileMPEGOpts *)buf;
  195.  
  196.     if (pp->len != sizeof(InputFileMPEGOpts))
  197.         return false;
  198.  
  199.     opts = *pp;
  200.  
  201.     return true;
  202. }
  203.  
  204. int InputFileMPEGOptions::write(char *buf, int buflen) {
  205.     InputFileMPEGOpts *pp = (InputFileMPEGOpts *)buf;
  206.  
  207.     if (buflen<sizeof(InputFileMPEGOpts))
  208.         return 0;
  209.  
  210.     opts.len = sizeof(InputFileMPEGOpts);
  211.     *pp = opts;
  212.  
  213.     return sizeof(InputFileMPEGOpts);
  214. }
  215.  
  216. ///////
  217.  
  218. BOOL APIENTRY InputFileMPEGOptions::SetupDlgProc( HWND hDlg, UINT message, UINT wParam, LONG lParam) {
  219.     InputFileMPEGOptions *thisPtr = (InputFileMPEGOptions *)GetWindowLong(hDlg, DWL_USER);
  220.  
  221.     switch(message) {
  222.         case WM_INITDIALOG:
  223.             SetWindowLong(hDlg, DWL_USER, lParam);
  224.             CheckDlgButton(hDlg, IDC_MPEG_ALL_FRAMES, TRUE);
  225.             return TRUE;
  226.  
  227.         case WM_COMMAND:
  228.             if (LOWORD(wParam) == IDCANCEL) {
  229.                 if (IsDlgButtonChecked(hDlg, IDC_MPEG_I_FRAMES_ONLY    ))
  230.                     thisPtr->opts.iDecodeMode = InputFileMPEGOptions::DECODE_NO_B | InputFileMPEGOptions::DECODE_NO_P;
  231.  
  232.                 if (IsDlgButtonChecked(hDlg, IDC_MPEG_IP_FRAMES_ONLY))
  233.                     thisPtr->opts.iDecodeMode = InputFileMPEGOptions::DECODE_NO_B;
  234.  
  235.                 if (IsDlgButtonChecked(hDlg, IDC_MPEG_ALL_FRAMES    ))
  236.                     thisPtr->opts.iDecodeMode = 0;
  237.  
  238.                 thisPtr->opts.fAcceptPartial = !!IsDlgButtonChecked(hDlg, IDC_MPEG_ACCEPTPARTIAL);
  239.  
  240.                 EndDialog(hDlg, 0);
  241.                 return TRUE;
  242.             }
  243.             break;
  244.     }
  245.  
  246.     return FALSE;
  247. }
  248.  
  249. //////////////////////////////////////////////////////////////////////////
  250. //
  251. //
  252. //                    MPEGPacketInfo/MPEGSampleInfo
  253. //
  254. //
  255. //////////////////////////////////////////////////////////////////////////
  256.  
  257.  
  258. struct MPEGPacketInfo {
  259.     __int64        file_pos;
  260.     __int64        stream_pos;
  261. };
  262.  
  263. struct MPEGSampleInfo {
  264.     __int64            stream_pos;
  265.     int                size;
  266.     union {
  267.         struct {
  268.             char            frame_type;
  269.             char            subframe_num;        // cannot have >132 (exact?) frames per GOP
  270.             char            _pad[2];
  271.         };
  272.  
  273.         struct {
  274.             long            header;
  275.         };
  276.     };
  277. };
  278.  
  279. //////////////////////////////////////////////////////////////////////////
  280. //
  281. //
  282. //                    InputFileMPEG
  283. //
  284. //
  285. //////////////////////////////////////////////////////////////////////////
  286.  
  287. class AudioSourceMPEG;
  288. class VideoSourceMPEG;
  289.  
  290. class InputFileMPEG : public InputFile {
  291. friend VideoSourceMPEG;
  292. friend AudioSourceMPEG;
  293. private:
  294.     __int64 file_len, file_cpos;
  295.     char *video_packet_buffer;
  296.     char *audio_packet_buffer;
  297.     MPEGPacketInfo *video_packet_list;
  298.     MPEGSampleInfo *video_sample_list;
  299.     MPEGPacketInfo *audio_packet_list;
  300.     MPEGSampleInfo *audio_sample_list;
  301.     int packets, apackets;
  302.     int frames, aframes;
  303.     int last_packet[2];
  304.     int width, height;
  305.     long frame_rate;
  306.     bool fInterleaved, fHasAudio, fIsVCD;
  307.     bool fAbort;
  308.  
  309.     long audio_first_header;
  310.  
  311.     int iDecodeMode;
  312.     bool fAcceptPartial;
  313.     bool fAudioBadPad;
  314.  
  315.     FastReadStream *pFastRead;
  316.     int fh;
  317.  
  318.     static const char szME[];
  319.  
  320.     enum {
  321.         RESERVED_STREAM        = 0xbc,
  322.         PRIVATE_STREAM1        = 0xbd,
  323.         PADDING_STREAM        = 0xbe,
  324.         PRIVATE_STREAM2        = 0xbf,
  325.     };
  326.  
  327.     enum {
  328.         SCAN_BUFFER_SIZE    = 65536,
  329.     };
  330.  
  331.     char *    pScanBuffer;
  332.     char *    pScan;
  333.     char *    pScanLimit;
  334.     __int64    i64ScanCpos;
  335.  
  336.     void    StartScan();
  337.     bool    NextStartCode();
  338.     void    Skip(int bytes);
  339.  
  340.     int        Read() {
  341.         return pScan < pScanLimit ? (unsigned char)*pScan++ : _Read();
  342.     }
  343.     int        Read(void *, int, bool);
  344.  
  345.     int        _Read();
  346.     void    UnRead() {
  347.         --pScan;
  348.     }
  349.     void    EndScan();
  350.     __int64    Tell();
  351.  
  352.     void    ReadStream(void *buffer, __int64 pos, long len, bool fAudio);
  353.  
  354.     static BOOL CALLBACK ParseDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
  355.  
  356.     void setOptions(InputFileOptions *);
  357.     InputFileOptions *createOptions(const char *buf);
  358.     InputFileOptions *promptForOptions(HWND);
  359. public:
  360.     InputFileMPEG();
  361.     ~InputFileMPEG();
  362.  
  363.     void Init(char *szFile);
  364.     static void _InfoDlgThread(void *pvInfo);
  365.     static BOOL APIENTRY _InfoDlgProc( HWND hDlg, UINT message, UINT wParam, LONG lParam);
  366.     void InfoDialog(HWND hwndParent);
  367. };
  368.  
  369.  
  370. //////////////////////////////////////////////////////////////////////////
  371. //
  372. //
  373. //                        VideoSourceMPEG
  374. //
  375. //
  376. //////////////////////////////////////////////////////////////////////////
  377.  
  378. class VideoSourceMPEG : public VideoSource {
  379. private:
  380.     InputFileMPEG *parentPtr;
  381.  
  382.     long frame_forw, frame_back, frame_bidir;
  383.     long frame_type;
  384.  
  385.     BOOL fFBValid;
  386.  
  387.     LONG renumber_frame(LONG lSample);
  388.     LONG translate_frame(LONG lSample);
  389.     long prev_IP(long f);
  390.     long prev_I(long f);
  391.     bool is_I(long lSample);
  392.  
  393. public:
  394.     VideoSourceMPEG(InputFileMPEG *);
  395.     ~VideoSourceMPEG();
  396.  
  397.     BOOL init();
  398.     char getFrameTypeChar(long lFrameNum);
  399.     BOOL _isKey(LONG lSample);
  400.     virtual LONG nearestKey(LONG lSample);
  401.     virtual LONG prevKey(LONG lSample);
  402.     virtual LONG nextKey(LONG lSample);
  403.     bool setDecompressedFormat(int depth);
  404.     bool setDecompressedFormat(BITMAPINFOHEADER *pbih);
  405.     void invalidateFrameBuffer();
  406.     BOOL isFrameBufferValid();
  407.     void streamBegin(bool fRealTime);
  408.     void streamSetDesiredFrame(long frame_num);
  409.     long streamGetNextRequiredFrame(BOOL *is_preroll);
  410.     int streamGetRequiredCount(long *);
  411.     void *streamGetFrame(void *inputBuffer, long data_len, BOOL is_key, BOOL is_preroll, long frame_num);
  412.     void *getFrame(LONG frameNum);
  413.     int _read(LONG lStart, LONG lCount, LPVOID lpBuffer, LONG cbBuffer, LONG *lSamplesRead, LONG *lBytesRead);
  414. };
  415.  
  416. VideoSourceMPEG::VideoSourceMPEG(InputFileMPEG *parent) {
  417.     parentPtr = parent;
  418. }
  419.  
  420. BOOL VideoSourceMPEG::init() {
  421.     BITMAPINFOHEADER *bmih;
  422.     int w, h;
  423.  
  424.     fFBValid = FALSE;
  425.  
  426.     lSampleFirst = 0;
  427.     lSampleLast = parentPtr->frames;
  428.  
  429.     w = (parentPtr->width+15) & -16;
  430.     h = (parentPtr->height+1) & -2;
  431.  
  432.     if (!AllocFrameBuffer(w * h * 4 + 4))
  433.         throw MyMemoryError();
  434.  
  435.     if (!(bmih = (BITMAPINFOHEADER *)allocFormat(sizeof(BITMAPINFOHEADER))))
  436.         throw MyMemoryError();
  437.  
  438.     if (!(bmihDecompressedFormat = (BITMAPINFOHEADER *)allocmem(getFormatLen()))) throw MyMemoryError();
  439.  
  440.     bmih->biSize        = sizeof(BITMAPINFOHEADER);
  441.     bmih->biWidth        = w;
  442.     bmih->biHeight        = h;
  443.     bmih->biPlanes        = 1;
  444.     bmih->biBitCount    = 32;
  445.     bmih->biCompression    = 0xffffffff;
  446.     bmih->biSizeImage    = 0;
  447.     bmih->biXPelsPerMeter    = 0;
  448.     bmih->biYPelsPerMeter    = 0;
  449.     bmih->biClrUsed        = 0;
  450.     bmih->biClrImportant    = 0;
  451.  
  452.     streamInfo.fccType                    = streamtypeVIDEO;
  453.     streamInfo.fccHandler                = 0;
  454.     streamInfo.dwFlags                    = 0;
  455.     streamInfo.dwScale                    = 1000;
  456.     streamInfo.dwRate                    = parentPtr->frame_rate;
  457.     streamInfo.dwStart                    = 0;
  458.     streamInfo.dwLength                    = parentPtr->frames;
  459.     streamInfo.dwInitialFrames            = 0;
  460.     streamInfo.dwSuggestedBufferSize    = 0;
  461.     streamInfo.dwQuality                = 0xffffffffL;
  462.     streamInfo.dwSampleSize                = 0;
  463.     streamInfo.rcFrame.left                = 0;
  464.     streamInfo.rcFrame.top                = 0;
  465.     streamInfo.rcFrame.right            = w;
  466.     streamInfo.rcFrame.bottom            = h;
  467.  
  468.     return TRUE;
  469. }
  470.  
  471. VideoSourceMPEG::~VideoSourceMPEG() {
  472. }
  473.  
  474. bool VideoSourceMPEG::setDecompressedFormat(int depth) {
  475.     if (depth != 32 && depth != 24 && depth != 16) return FALSE;
  476.  
  477.     return VideoSource::setDecompressedFormat(depth);
  478. }
  479.  
  480. bool VideoSourceMPEG::setDecompressedFormat(BITMAPINFOHEADER *pbih) {
  481.     if (pbih->biCompression == BI_RGB)
  482.         return setDecompressedFormat(pbih->biBitCount);
  483.  
  484.     // Sanity-check format.
  485.  
  486.     BITMAPINFOHEADER *pbihInput = getImageFormat();
  487.  
  488.     if (pbih->biWidth != pbihInput->biWidth
  489.         || pbih->biHeight != pbihInput->biHeight
  490.         || pbih->biPlanes != 1)
  491.  
  492.         return false;
  493.  
  494.     do {
  495.         // Accept UYVY, YUYV, or YUY2 at 16-bits per pel.
  496.  
  497.         if (pbih->biBitCount == 16 && (isEqualFOURCC(pbih->biCompression, 'YVYU')
  498.             || isEqualFOURCC(pbih->biCompression, 'VYUY') || isEqualFOURCC(pbih->biCompression, '2YUY')))
  499.  
  500.             break;
  501.  
  502.         // Damn.
  503.  
  504.         return false;
  505.  
  506.     } while(0);
  507.  
  508.     // Looks good!
  509.  
  510.     memcpy(bmihDecompressedFormat, pbih, sizeof(BITMAPINFOHEADER));
  511.     invalidateFrameBuffer();
  512.  
  513.     return true;
  514. }
  515.  
  516. void VideoSourceMPEG::invalidateFrameBuffer() {
  517.     fFBValid = FALSE;
  518. }
  519.  
  520. BOOL VideoSourceMPEG::isFrameBufferValid() {
  521.     return fFBValid;
  522. }
  523.  
  524. char VideoSourceMPEG::getFrameTypeChar(long lFrameNum) {
  525.     if (lFrameNum<lSampleFirst || lFrameNum >= lSampleLast)
  526.         return ' ';
  527.  
  528.     lFrameNum = translate_frame(renumber_frame(lFrameNum));
  529.  
  530.     switch(parentPtr->video_sample_list[lFrameNum].frame_type) {
  531.     case MPEG_FRAME_TYPE_I:    return 'I';
  532.     case MPEG_FRAME_TYPE_P: return 'P';
  533.     case MPEG_FRAME_TYPE_B: return 'B';
  534.     default:
  535.         return ' ';
  536.     }
  537. }
  538.  
  539. BOOL VideoSourceMPEG::_isKey(LONG lSample) {
  540.     return lSample<0 || lSample>=lSampleLast ? false : parentPtr->video_sample_list[translate_frame(renumber_frame(lSample))].frame_type == MPEG_FRAME_TYPE_I;
  541. }
  542.  
  543. LONG VideoSourceMPEG::nearestKey(LONG lSample) {
  544.     if (_isKey(lSample))
  545.         return lSample;
  546.  
  547.     return prevKey(lSample);
  548. }
  549.  
  550. LONG VideoSourceMPEG::prevKey(LONG lSample) {
  551.     if (lSample < lSampleFirst) return -1;
  552.     if (lSample >= lSampleLast) lSample = lSampleLast-1;
  553.  
  554.     lSample = translate_frame(renumber_frame(lSample));
  555.  
  556.     while(--lSample >= lSampleFirst) {
  557.         if (parentPtr->video_sample_list[lSample].frame_type == MPEG_FRAME_TYPE_I)
  558.             return lSample + parentPtr->video_sample_list[lSample].subframe_num;
  559.     }
  560.  
  561.     return -1;
  562. }
  563.  
  564. LONG VideoSourceMPEG::nextKey(LONG lSample) {
  565.     if (lSample >= lSampleLast) return -1;
  566.     if (lSample < lSampleFirst) lSample = lSampleFirst;
  567.  
  568.     lSample = translate_frame(renumber_frame(lSample));
  569.  
  570.     while(++lSample < lSampleLast) {
  571.         if (parentPtr->video_sample_list[lSample].frame_type == MPEG_FRAME_TYPE_I)
  572.             return lSample + parentPtr->video_sample_list[lSample].subframe_num;
  573.     }
  574.  
  575.     return -1;
  576. }
  577.  
  578. void VideoSourceMPEG::streamBegin(bool fRealTime) {
  579.     frame_forw = frame_back = frame_bidir = -1;
  580. }
  581.  
  582. void VideoSourceMPEG::streamSetDesiredFrame(long frame_num) {
  583.     stream_desired_frame    = translate_frame(renumber_frame(frame_num));
  584.  
  585.     frame_type = parentPtr->video_sample_list[stream_desired_frame].frame_type;
  586.  
  587.     stream_current_frame    = stream_desired_frame;
  588.  
  589.     _RPT2(0,"Requested frame: %ld (%ld)\n", frame_num, stream_desired_frame);
  590.  
  591.     switch(frame_type) {
  592.     case MPEG_FRAME_TYPE_P:
  593.         while(frame_forw != stream_current_frame && parentPtr->video_sample_list[stream_current_frame].frame_type != MPEG_FRAME_TYPE_I && stream_current_frame>0)
  594. //            --stream_current_frame;
  595.             stream_current_frame = prev_IP(stream_current_frame);
  596.  
  597.         // Avoid decoding a I/P frame twice.
  598.  
  599.         if (frame_forw == stream_current_frame && stream_current_frame != stream_desired_frame)
  600.             ++stream_current_frame;
  601.  
  602.         break;
  603.     case MPEG_FRAME_TYPE_B:
  604.         {
  605.             long f,b;
  606.             long last_IP;
  607.  
  608.             while(stream_current_frame>0 && parentPtr->video_sample_list[stream_current_frame].frame_type == MPEG_FRAME_TYPE_B)
  609.                 --stream_current_frame;
  610.  
  611.             f = stream_current_frame;    // forward predictive frame
  612.  
  613.             if (stream_current_frame>0) --stream_current_frame;
  614.  
  615.             while(stream_current_frame>0 && parentPtr->video_sample_list[stream_current_frame].frame_type == MPEG_FRAME_TYPE_B)
  616.                 --stream_current_frame;
  617.  
  618.             b = stream_current_frame;    // backward predictive frame
  619.  
  620.             _RPT4(0,"B-frame requested: desire (%d,%d), have (%d,%d)\n", b, f, frame_back, frame_forw);
  621.  
  622.             if (frame_forw == f && frame_back == b) {
  623.                 stream_current_frame = stream_desired_frame;
  624.                 return;    // we got lucky!!!
  625.             }
  626.  
  627.             // Maybe we only need to read the next I/P frame...
  628.  
  629.             if (frame_forw == b) {
  630.                 stream_current_frame = f;
  631.                 return;
  632.             }
  633.  
  634.             // DAMN.  Back to last I/P; if it's an I, back up to previous I
  635.  
  636.             if (f==0) return; // No forward predictive frame, use first I
  637.  
  638.             if (parentPtr->video_sample_list[f].frame_type == MPEG_FRAME_TYPE_I)
  639.                 stream_current_frame = f-1;
  640.  
  641.             stream_current_frame = prev_IP(stream_current_frame);
  642.             while(stream_current_frame>0 && parentPtr->video_sample_list[stream_current_frame].frame_type != MPEG_FRAME_TYPE_I) {
  643.                 last_IP = stream_current_frame;
  644.  
  645.                 stream_current_frame = prev_IP(stream_current_frame);
  646.  
  647.                 if (stream_current_frame == frame_back && last_IP == frame_forw) {
  648.                     stream_current_frame = frame_forw+1;
  649.                     break;
  650.                 }
  651.             }
  652.  
  653. //            _RPT1(0,"Beginning B-frame scan: %ld\n", stream_current_frame);
  654.  
  655.         }
  656.         break;
  657.     }
  658. }
  659.  
  660. long VideoSourceMPEG::streamGetNextRequiredFrame(BOOL *is_preroll) {
  661.     if (    frame_forw == stream_desired_frame
  662.         ||    frame_back == stream_desired_frame
  663.         ||    frame_bidir == stream_desired_frame) {
  664.  
  665.         *is_preroll = FALSE;
  666.  
  667.         return -1;
  668.     }
  669.  
  670. //    _RPT1(0,"current: %ld\n", stream_current_frame);
  671.  
  672.     switch(frame_type) {
  673.  
  674.         case MPEG_FRAME_TYPE_P:
  675.         case MPEG_FRAME_TYPE_B:
  676.  
  677.             while(stream_current_frame != stream_desired_frame
  678.                     && parentPtr->video_sample_list[stream_current_frame].frame_type == MPEG_FRAME_TYPE_B)
  679.  
  680.                     ++stream_current_frame;
  681.  
  682.             break;
  683.     }
  684.  
  685.     switch(parentPtr->video_sample_list[stream_current_frame].frame_type) {
  686.         case MPEG_FRAME_TYPE_I:
  687.         case MPEG_FRAME_TYPE_P:
  688.             frame_back = frame_forw;
  689.             frame_forw = stream_current_frame;
  690.             break;
  691.         case MPEG_FRAME_TYPE_B:
  692.             frame_bidir = stream_current_frame;
  693.             break;
  694.     }
  695.  
  696.     *is_preroll = (stream_desired_frame != stream_current_frame);
  697.  
  698. //    _RPT1(0,"MPEG: You want frame %ld.\n", stream_current_frame);
  699.  
  700.     return stream_current_frame++;
  701. }
  702.  
  703. int VideoSourceMPEG::streamGetRequiredCount(long *pSize) {
  704.     int current = stream_current_frame;
  705.     int needed = 1;
  706.     long size = 0;
  707.  
  708.     if (frame_forw == stream_desired_frame
  709.         || frame_back == stream_desired_frame
  710.         || frame_bidir == stream_desired_frame) {
  711.         if (pSize)
  712.             *pSize = 0;
  713.         return 0;
  714.     }
  715.  
  716.  
  717.     if (frame_type == MPEG_FRAME_TYPE_I) {
  718.         if (*pSize)
  719.             *pSize = parentPtr->video_sample_list[current].size;
  720.         return 1;
  721.     }
  722.  
  723.     while(current < stream_desired_frame) {
  724.  
  725.         while(current != stream_desired_frame
  726.                 && parentPtr->video_sample_list[current].frame_type == MPEG_FRAME_TYPE_B)
  727.  
  728.                 ++current;
  729.  
  730.         size += parentPtr->video_sample_list[current].size;
  731.  
  732.         ++needed;
  733.         ++current;
  734.     }
  735.  
  736.     if (pSize)
  737.         *pSize = size;
  738.  
  739.     return needed;
  740. }
  741.  
  742. void *VideoSourceMPEG::streamGetFrame(void *inputBuffer, long data_len, BOOL is_key, BOOL is_preroll, long frame_num) {
  743.     int buffer;
  744.  
  745.     if (data_len<=1 && frame_num < lSampleLast)
  746.         frame_num = translate_frame(renumber_frame(frame_num));
  747.  
  748.     _RPT2(0,"Attempting to fetch frame %d [%c].\n", frame_num, "0IPBD567"[parentPtr->video_sample_list[frame_num].frame_type]);
  749.  
  750.     if (is_preroll || (buffer = mpeg_lookup_frame(frame_num))<0) {
  751.         if (!frame_num) mpeg_reset();
  752. //        _RPT2(0,"Decoding frame %d (%d bytes)\n", frame_num, data_len);
  753.  
  754.         // the "read" function gave us the extra 3 bytes we need
  755.  
  756.         if (data_len<=3) {
  757.             if (MMX_enabled)
  758.                 __asm emms
  759.  
  760.             return lpvBuffer;    // HACK
  761.         }
  762.  
  763.         mpeg_decode_frame(inputBuffer, data_len, frame_num);
  764.     }
  765.     
  766.     if (!is_preroll) {
  767.         int nBuffer = mpeg_lookup_frame(frame_num);
  768.  
  769.         if (bmihDecompressedFormat->biCompression == 'YVYU')
  770.             mpeg_convert_frameUYVY16(lpvBuffer, nBuffer);
  771.         else if (bmihDecompressedFormat->biCompression == '2YUY')
  772.             mpeg_convert_frameYUY216(lpvBuffer, nBuffer);
  773.         else if (bmihDecompressedFormat->biBitCount == 16)
  774.             mpeg_convert_frame16(lpvBuffer, nBuffer);
  775.         else if (bmihDecompressedFormat->biBitCount == 24)
  776.             mpeg_convert_frame24(lpvBuffer, nBuffer);
  777.         else
  778.             mpeg_convert_frame32(lpvBuffer, nBuffer);
  779.         fFBValid = TRUE;
  780.     }
  781.  
  782.     if (MMX_enabled)
  783.         __asm emms
  784.  
  785.     return lpvBuffer;
  786. }
  787.  
  788. void *VideoSourceMPEG::getFrame(LONG frameNum) {
  789.     LONG lCurrent, lKey;
  790.     MPEGSampleInfo *msi;
  791.     int buffer;
  792.  
  793.     frameNum = translate_frame(renumber_frame(frameNum));
  794.  
  795.     // Do we have the buffer stored somewhere?
  796.  
  797.     if ((buffer = mpeg_lookup_frame(frameNum))>=0) {
  798.         if (bmihDecompressedFormat->biCompression == 'YVYU')
  799.             mpeg_convert_frameUYVY16(lpvBuffer, buffer);
  800.         else if (bmihDecompressedFormat->biCompression == '2YUY')
  801.             mpeg_convert_frameYUY216(lpvBuffer, buffer);
  802.         else if (bmihDecompressedFormat->biBitCount == 16)
  803.             mpeg_convert_frame16(lpvBuffer, buffer);
  804.         else if (bmihDecompressedFormat->biBitCount == 24)
  805.             mpeg_convert_frame24(lpvBuffer, buffer);
  806.         else
  807.             mpeg_convert_frame32(lpvBuffer, buffer);
  808.  
  809.         fFBValid = TRUE;
  810.  
  811.         return lpvBuffer;
  812.     }
  813.  
  814.     // I-frames have no prediction, so all we have to do there is decode the I-frame.
  815.     // P-frames decode from the last P or I, so we have to decode all frames from the
  816.     //        last I-frame.
  817.     // B-frames decode from the last two P or I.  If the last I/P-frame is a P-frame,
  818.     //        we can just decode from the last I.  If the last frame is an I-frame, we
  819.     //        need to back up *two* I-frames.
  820.  
  821.     // possible cases:
  822.     //
  823.     //    I-frame        1)    Decompress the I-frame.
  824.     //    P-frame        1)    No buffer contains the required pre-frame - read up from I-frame.
  825.     //                2)    Earlier I/P-frame in a buffer - predict from that.
  826.     //    B-frame        1)    No buffers with required prediction frames - read up from I-frame.
  827.     //                2)    Forward prediction frame only - read the backward prediction I/P.
  828.     //                3)    Backward prediction frame only - 
  829.  
  830.     lCurrent = frameNum;
  831.  
  832.     if (!is_I(frameNum) && -1 == (lCurrent = prev_I(frameNum)))
  833.         throw MyError("Unable to decode: cannot find I-frame");
  834.  
  835.     switch(parentPtr->video_sample_list[frameNum].frame_type) {
  836.  
  837.     // if it's a B-frame, back off from the current frame; if the previous I/P frame
  838.     // is an I, we will need to back off again
  839.  
  840.     case MPEG_FRAME_TYPE_B:
  841.         lKey = frameNum;
  842.  
  843.         while(lKey > lCurrent && parentPtr->video_sample_list[lKey].frame_type == MPEG_FRAME_TYPE_B) --lKey;
  844.  
  845.         if (is_I(lKey))
  846.             if (-1 != (lKey = prev_I(lKey)))
  847.                 lCurrent = lKey;
  848.         break;
  849.  
  850.     // P-frame: start backing up from the current frame to the last I-frame.  If we find
  851.     //            a I or P frame in one of our buffers beforehand, then swap it to the FORWARD
  852.     //            buffer and start predicting off of that.
  853.  
  854.     case MPEG_FRAME_TYPE_P:
  855.         lKey = lCurrent;
  856.         buffer = -1;
  857.         while(lKey < frameNum) {
  858.             if (parentPtr->video_sample_list[lKey].frame_type != MPEG_FRAME_TYPE_B)
  859.                 if ((buffer = mpeg_lookup_frame(lKey))>=0)
  860.                     break;
  861.             ++lKey;
  862.         }
  863.  
  864.         if (buffer>=0) {
  865.             lCurrent = lKey+1;
  866.             if (buffer != MPEG_BUFFER_FORWARD)
  867.                 mpeg_swap_buffers(buffer, MPEG_BUFFER_FORWARD);
  868.         }
  869.         break;
  870.     }
  871.  
  872.     msi = &parentPtr->video_sample_list[lCurrent];
  873.     do {
  874.         //_RPT4(0,"getFrame: looking for %ld, at %ld (%c-frame, #%d)\n"
  875.         //            ,frameNum
  876.         //            ,lCurrent
  877.         //            ," IPBD567"[msi->frame_type]
  878.         //            ,msi->subframe_num);
  879.  
  880.         if (lCurrent == frameNum || (msi->frame_type == MPEG_FRAME_TYPE_I || msi->frame_type == MPEG_FRAME_TYPE_P)) {
  881.  
  882.             parentPtr->ReadStream(parentPtr->video_packet_buffer, msi->stream_pos, msi->size, FALSE);
  883.  
  884.             mpeg_decode_frame(parentPtr->video_packet_buffer, msi->size+4, lCurrent);
  885.  
  886.         }
  887.  
  888.         ++msi;
  889.     } while(lCurrent++ < frameNum);
  890.  
  891.     --msi;
  892.  
  893.     if (bmihDecompressedFormat->biCompression == 'YVYU')
  894.         mpeg_convert_frameUYVY16(lpvBuffer, msi->frame_type>2 ? MPEG_BUFFER_BIDIRECTIONAL : MPEG_BUFFER_FORWARD);
  895.     else if (bmihDecompressedFormat->biCompression == '2YUY')
  896.         mpeg_convert_frameYUY216(lpvBuffer, msi->frame_type>2 ? MPEG_BUFFER_BIDIRECTIONAL : MPEG_BUFFER_FORWARD);
  897.     else if (bmihDecompressedFormat->biBitCount == 16)
  898.         mpeg_convert_frame16(lpvBuffer, msi->frame_type>2 ? MPEG_BUFFER_BIDIRECTIONAL : MPEG_BUFFER_FORWARD);
  899.     else if (bmihDecompressedFormat->biBitCount == 24)
  900.         mpeg_convert_frame24(lpvBuffer, msi->frame_type>2 ? MPEG_BUFFER_BIDIRECTIONAL : MPEG_BUFFER_FORWARD);
  901.     else
  902.         mpeg_convert_frame32(lpvBuffer, msi->frame_type>2 ? MPEG_BUFFER_BIDIRECTIONAL : MPEG_BUFFER_FORWARD);
  903.  
  904.     if (MMX_enabled)
  905.         __asm emms
  906.  
  907.     fFBValid = TRUE;
  908.  
  909.     return getFrameBuffer();
  910. }
  911.  
  912. int VideoSourceMPEG::_read(LONG lStart, LONG lCount, LPVOID lpBuffer, LONG cbBuffer, LONG *lBytesRead, LONG *lSamplesRead) {
  913.     MPEGSampleInfo *msi = &parentPtr->video_sample_list[lStart];
  914.     long len = msi->size;
  915.  
  916.     // Check to see if this is a frame type we're omitting
  917.  
  918.     switch(msi->frame_type) {
  919.         case MPEG_FRAME_TYPE_P:
  920.             if (parentPtr->iDecodeMode & InputFileMPEGOptions::DECODE_NO_P) {
  921.                 *lBytesRead = 1;
  922.                 *lSamplesRead = 1;
  923.                 return AVIERR_OK;
  924.             }
  925.             break;
  926.         case MPEG_FRAME_TYPE_B:
  927.             if (parentPtr->iDecodeMode & InputFileMPEGOptions::DECODE_NO_B) {
  928.                 *lBytesRead = 1;
  929.                 *lSamplesRead = 1;
  930.                 return AVIERR_OK;
  931.             }
  932.             break;
  933.     }
  934.  
  935.     // We must add 3 bytes to hold the end marker when we decode
  936.  
  937.     if (!lpBuffer) {
  938.         if (lSamplesRead) *lSamplesRead = 1;
  939.         if (lBytesRead) *lBytesRead = len+4;
  940.         return AVIERR_OK;
  941.     }
  942.  
  943.     if (len > cbBuffer) {
  944.         if (lSamplesRead) *lSamplesRead = 0;
  945.         if (lBytesRead) *lBytesRead = 0;
  946.         return AVIERR_BUFFERTOOSMALL;
  947.     }
  948.  
  949.     parentPtr->ReadStream(lpBuffer, msi->stream_pos, len, FALSE);
  950.  
  951.     if (lSamplesRead) *lSamplesRead = 1;
  952.     if (lBytesRead) *lBytesRead = len+4;
  953.  
  954.     return AVIERR_OK;
  955. }
  956.  
  957. ///////
  958.  
  959. long VideoSourceMPEG::renumber_frame(LONG lSample) {
  960.     LONG lKey=lSample, lCurrent;
  961.  
  962.     if (lSample < lSampleFirst || lSample >= lSampleLast || (!is_I(lSample) && (lKey = prev_I(lSample))==-1))
  963.         throw MyError("Frame not found (looking for %ld)", lSample);
  964.  
  965.     lCurrent = lKey;
  966.     do {
  967.         if (lSample-lKey == parentPtr->video_sample_list[lCurrent].subframe_num)
  968.             return lCurrent;
  969.     } while(++lCurrent < lSampleLast && !is_I(lCurrent));
  970.  
  971.     throw MyError("Frame not found (looking for %ld)", lSample);
  972.  
  973.     return -1;    // throws can't return!
  974. }
  975.  
  976. bool VideoSourceMPEG::is_I(long lSample) {
  977.     return parentPtr->video_sample_list[lSample].frame_type == MPEG_FRAME_TYPE_I;
  978. }
  979.  
  980. long VideoSourceMPEG::prev_I(long lSample) {
  981.     if (lSample < lSampleFirst) return -1;
  982.     if (lSample >= lSampleLast) lSample = lSampleLast-1;
  983.  
  984.     while(--lSample >= lSampleFirst) {
  985.         if (parentPtr->video_sample_list[lSample].frame_type == MPEG_FRAME_TYPE_I)
  986.             return lSample;
  987.     }
  988.  
  989.     return -1;
  990. }
  991.  
  992. long VideoSourceMPEG::prev_IP(long f) {
  993.     if (f<=0) return f;
  994.  
  995.     do
  996.         --f;
  997.     while (f>0 && parentPtr->video_sample_list[f].frame_type == MPEG_FRAME_TYPE_B);
  998.  
  999.     return f;
  1000. }
  1001.  
  1002. long VideoSourceMPEG::translate_frame(LONG lSample) {
  1003.     MPEGSampleInfo *msi = &parentPtr->video_sample_list[lSample];
  1004.  
  1005.     // Check to see if this is a frame type we're omitting; if so,
  1006.     // keep backing up until it's one we're not.
  1007.  
  1008.     while(lSample > 0) {
  1009.         switch(msi->frame_type) {
  1010.             case MPEG_FRAME_TYPE_P:
  1011.                 if (!(parentPtr->iDecodeMode & InputFileMPEGOptions::DECODE_NO_P))
  1012.                     return lSample;
  1013.  
  1014.                 break;
  1015.             case MPEG_FRAME_TYPE_B:
  1016.                 if (!(parentPtr->iDecodeMode & InputFileMPEGOptions::DECODE_NO_B))
  1017.                     return lSample;
  1018.  
  1019.                 break;
  1020.             default:
  1021.                 return lSample;
  1022.         }
  1023.  
  1024.         --lSample;
  1025.         --msi;
  1026.     }
  1027.  
  1028.     return lSample;
  1029. }
  1030.  
  1031. //////////////////////////////////////////////////////////////////////////
  1032. //
  1033. //
  1034. //                        AudioSourceMPEG
  1035. //
  1036. //
  1037. //////////////////////////////////////////////////////////////////////////
  1038.  
  1039.     // 0000F0FF 12 bits    sync mark
  1040.     //
  1041.     // 00000800  1 bit    version
  1042.     // 00000600  2 bits    layer (3 = layer I, 2 = layer II, 1 = layer III)
  1043.     // 00000100  1 bit    error protection (0 = enabled)
  1044.     //
  1045.     // 00F00000  4 bits    bitrate_index
  1046.     // 000C0000  2 bits    sampling_freq
  1047.     // 00020000  1 bit    padding
  1048.     // 00010000  1 bit    extension
  1049.     //
  1050.     // C0000000  2 bits    mode (0=stereo, 1=joint stereo, 2=dual channel, 3=mono)
  1051.     // 30000000  2 bits    mode_ext
  1052.     // 08000000  1 bit    copyright
  1053.     // 04000000  1 bit    original
  1054.     // 03000000  2 bits    emphasis
  1055.  
  1056. #define MPEGAHDR_SYNC_MASK            (0x0000F0FF)
  1057. #define MPEGAHDR_VERSION_MASK        (0x00000800)
  1058. #define    MPEGAHDR_LAYER_MASK            (0x00000600)
  1059. #define MPEGAHDR_CRC_MASK            (0x00000100)
  1060. #define MPEGAHDR_BITRATE_MASK        (0x00F00000)
  1061. #define MPEGAHDR_SAMPLERATE_MASK    (0x000C0000)
  1062. #define MPEGAHDR_PADDING_MASK        (0x00020000)
  1063. #define MPEGAHDR_EXT_MASK            (0x00010000)
  1064. #define MPEGAHDR_MODE_MASK            (0xC0000000)
  1065. #define MPEGAHDR_MODEEXT_MASK        (0x30000000)
  1066. #define MPEGAHDR_COPYRIGHT_MASK        (0x08000000)
  1067. #define MPEGAHDR_ORIGINAL_MASK        (0x04000000)
  1068. #define MPEGAHDR_EMPHASIS_MASK        (0x03000000)
  1069.  
  1070. #ifdef ENABLE_AUDIO_SUPPORT
  1071.  
  1072. class AudioSourceMPEG : public AudioSource, IAMPBitsource {
  1073. private:
  1074.     InputFileMPEG *parentPtr;
  1075.     IAMPDecoder *iad;
  1076.     void *pkt_buffer;
  1077.     short sample_buffer[1152*2][2];
  1078.     char *pDecoderPoint;
  1079.     char *pDecoderLimit;
  1080.  
  1081.     long lCurrentPacket;
  1082.     long lFrameLen, lFrameDataLen;
  1083.     int layer;
  1084.  
  1085.     BOOL _isKey(LONG lSample);
  1086.  
  1087. public:
  1088.     AudioSourceMPEG(InputFileMPEG *);
  1089.     ~AudioSourceMPEG();
  1090.  
  1091.     // AudioSource methods
  1092.  
  1093.     BOOL init();
  1094.     int _read(LONG lStart, LONG lCount, LPVOID lpBuffer, LONG cbBuffer, LONG *lSamplesRead, LONG *lBytesRead);
  1095.  
  1096.     // IAMPBitsource methods
  1097.  
  1098.     int read(void *buffer, int bytes);
  1099.  
  1100. };
  1101.  
  1102. AudioSourceMPEG::AudioSourceMPEG(InputFileMPEG *pp) : AudioSource() {
  1103.     parentPtr = pp;
  1104.  
  1105.     if (!(pkt_buffer = new char[8192]))
  1106.         throw MyMemoryError();
  1107.  
  1108.     if (!(iad = CreateAMPDecoder())) {
  1109.         delete pkt_buffer;
  1110.         throw MyMemoryError();
  1111.     }
  1112.  
  1113.     lCurrentPacket = -1;
  1114. }
  1115.  
  1116. AudioSourceMPEG::~AudioSourceMPEG() {
  1117.     delete pkt_buffer;
  1118.     delete iad;
  1119. }
  1120.  
  1121. BOOL AudioSourceMPEG::_isKey(LONG lSample) {
  1122.     return TRUE;
  1123. }
  1124.  
  1125. static const int bitrate[3][15] = {
  1126.           {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},
  1127.           {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384},
  1128.           {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}
  1129.         };
  1130.  
  1131. static const long samp_freq[4] = {44100, 48000, 32000, 0};
  1132.  
  1133. BOOL AudioSourceMPEG::init() {
  1134.     WAVEFORMATEX *wfex;
  1135.  
  1136.     layer = 4 - ((parentPtr->audio_first_header>>9)&3);
  1137.  
  1138.     lSampleFirst = 0;
  1139.     lSampleLast = parentPtr->aframes * (layer==1 ? 384 : 1152);
  1140.  
  1141.     if (layer == 3) {
  1142.         lFrameLen = MulDiv(
  1143.                             bitrate    [3-((parentPtr->audio_first_header>>9)&3)][(parentPtr->audio_first_header>>20)&15],
  1144.                             144000,
  1145.                             samp_freq[(parentPtr->audio_first_header>>18)&3]);
  1146.  
  1147.         lFrameDataLen = lFrameLen - (((parentPtr->audio_first_header & 0xC0000000) == 0xC0000000)
  1148.             ? 13 : 21);
  1149.     }
  1150.  
  1151.     if (!(wfex = (WAVEFORMATEX*)allocFormat(sizeof(PCMWAVEFORMAT))))
  1152.         return FALSE;
  1153.  
  1154.     // [?] * [bits/sec] / [samples/sec] = [bytes/frame]
  1155.     // [?] * [bits/sample] = [bytes/frame]
  1156.     // [?] * [.125 byte/bit] * [bits/sample] = [bytes/frame]
  1157.     // [samples/frame]
  1158.  
  1159.  
  1160.     wfex->wFormatTag        = WAVE_FORMAT_PCM;
  1161.     wfex->nChannels            = ((parentPtr->audio_first_header & 0xC0000000) == 0xC0000000)
  1162.                                 ? 1 : 2;
  1163.     wfex->nBlockAlign        = wfex->nChannels*2;
  1164.     wfex->nSamplesPerSec    = samp_freq[(parentPtr->audio_first_header>>18)&3];
  1165.     wfex->nAvgBytesPerSec    = wfex->nSamplesPerSec * wfex->nBlockAlign;
  1166.     wfex->wBitsPerSample    = 16;
  1167.  
  1168.     streamInfo.fccType                    = streamtypeAUDIO;
  1169.     streamInfo.fccHandler                = 0;
  1170.     streamInfo.dwFlags                    = 0;
  1171.     streamInfo.dwScale                    = wfex->nBlockAlign;
  1172.     streamInfo.dwRate                    = samp_freq[(parentPtr->audio_first_header>>18)&3] * wfex->nBlockAlign;
  1173.     streamInfo.dwStart                    = 0;
  1174.     streamInfo.dwLength                    = parentPtr->aframes * (layer==1 ? 384 : 1152);
  1175.     streamInfo.dwInitialFrames            = 0;
  1176.     streamInfo.dwSuggestedBufferSize    = 0;
  1177.     streamInfo.dwQuality                = 0xffffffffL;
  1178.     streamInfo.dwSampleSize                = wfex->nBlockAlign;
  1179.     streamInfo.rcFrame.left                = 0;
  1180.     streamInfo.rcFrame.top                = 0;
  1181.     streamInfo.rcFrame.right            = 0;
  1182.     streamInfo.rcFrame.bottom            = 0;
  1183.  
  1184.     try {
  1185.         iad->Init();
  1186.         iad->setSource(this);
  1187.     } catch(int i) {
  1188.         throw MyError(iad->getErrorString(i));
  1189.     }
  1190.  
  1191.     return TRUE;
  1192. }
  1193.  
  1194. int AudioSourceMPEG::_read(LONG lStart, LONG lCount, LPVOID lpBuffer, LONG cbBuffer, LONG *lBytesRead, LONG *lSamplesRead) {
  1195.     long lAudioPacket;
  1196.     MPEGSampleInfo *msi;
  1197.     long len;
  1198.     long samples, ba = getWaveFormat()->nBlockAlign;
  1199.  
  1200.     if (layer==1) {
  1201.         lAudioPacket = lStart/384;
  1202.         samples = 384 - (lStart % 384);
  1203.     } else {
  1204.         lAudioPacket = lStart/1152;
  1205.         samples = 1152 - (lStart % 1152);
  1206.     }
  1207.  
  1208.     if (lCount != AVISTREAMREAD_CONVENIENT)
  1209.         if (samples > lCount) samples = lCount;
  1210.  
  1211. #if 0
  1212.     if (samples*ba > cbBuffer) {
  1213.         if (lSamplesRead) *lSamplesRead = 0;
  1214.         if (lBytesRead) *lBytesRead = 0;
  1215.         return AVIERR_BUFFERTOOSMALL;
  1216.     }
  1217. #else
  1218.     if (samples*ba > cbBuffer && lpBuffer) {
  1219.         samples = cbBuffer / ba;
  1220.  
  1221.         if (samples <= 0) {
  1222.             if (lSamplesRead) *lSamplesRead = 0;
  1223.             if (lBytesRead) *lBytesRead = 0;
  1224.             return AVIERR_BUFFERTOOSMALL;
  1225.         }
  1226.     }
  1227. #endif
  1228.  
  1229.     if (!lpBuffer) {
  1230.         if (lSamplesRead) *lSamplesRead = samples;
  1231.         if (lBytesRead) *lBytesRead = samples * ba;
  1232.         return AVIERR_OK;
  1233.     }
  1234.  
  1235.     // Layer 3 audio is a royal pain in the *(@#&$*( because the data can start
  1236.     // up to 511 bytes behind the beginning of the current frame.  To get around
  1237.     // this problem, we preread up to 511 bytes from the previous frame.
  1238.  
  1239.  
  1240.     if (lCurrentPacket != lAudioPacket) {
  1241.         try {
  1242.  
  1243.             if (layer!=3 || lCurrentPacket<0 || lCurrentPacket+1 != lAudioPacket) {
  1244. //                _RPT0(0,"Resetting...\n");
  1245.                 iad->Reset();
  1246.  
  1247.                 lCurrentPacket = lAudioPacket;
  1248.  
  1249.                 if (layer == 3) {
  1250.                     lCurrentPacket -= (510 + lFrameDataLen) / lFrameDataLen;
  1251.                 } else
  1252.                     --lCurrentPacket;
  1253.  
  1254.                 if (lCurrentPacket < 0)
  1255.                     lCurrentPacket = 0;
  1256.             } else
  1257.                 lCurrentPacket = lAudioPacket;
  1258.  
  1259.             do {
  1260.                 _RPT1(0,"Decoding packet: %d\n", lCurrentPacket);
  1261.  
  1262.                 msi = &parentPtr->audio_sample_list[lCurrentPacket];
  1263.                 len = msi->size;
  1264.  
  1265.                 parentPtr->ReadStream(pkt_buffer, msi->stream_pos, len, TRUE);
  1266.  
  1267.                 pDecoderPoint = (char *)pkt_buffer;
  1268.                 pDecoderLimit = (char *)pkt_buffer + len;
  1269.  
  1270.                 if ((unsigned char)pDecoderPoint[0] != 0xff || ((unsigned char)pDecoderPoint[1]&0xf0)!=0xf0)
  1271.                     throw MyError("Sync error");
  1272.  
  1273.                 iad->setDestination((short *)sample_buffer);
  1274.                 iad->ReadHeader();
  1275.                 if (layer==3 && lCurrentPacket < lAudioPacket)
  1276.                     iad->PrereadFrame();
  1277.                 else
  1278.                     iad->DecodeFrame();
  1279.  
  1280.             } while(++lCurrentPacket <= lAudioPacket);
  1281.             --lCurrentPacket;
  1282.         } catch(int i) {
  1283.             throw MyError("MPEG-1 audio decode error: %s", iad->getErrorString(i));
  1284.         }
  1285.     }
  1286.  
  1287.     memcpy(lpBuffer, (short *)sample_buffer + (lStart%(layer==1?384:1152))*(ba/2), samples*ba);
  1288.  
  1289.     if (lSamplesRead) *lSamplesRead = samples;
  1290.     if (lBytesRead) *lBytesRead = samples*ba;
  1291.  
  1292.     return AVIERR_OK;
  1293. }
  1294.  
  1295. int AudioSourceMPEG::read(void *buffer, int bytes) {
  1296.     if (pDecoderPoint+bytes > pDecoderLimit)
  1297.         throw MyError("Incomplete audio frame");
  1298.  
  1299.     memcpy(buffer, pDecoderPoint, bytes);
  1300.     pDecoderPoint += bytes;
  1301.  
  1302.     return bytes;
  1303. }
  1304.  
  1305. #endif
  1306.  
  1307. //////////////////////////////////////////////////////////////////////////
  1308. //
  1309. //
  1310. //                    MPEGAudioParser
  1311. //
  1312. //
  1313. //////////////////////////////////////////////////////////////////////////
  1314.  
  1315. static bool MPEG_check_audio_header_validity(long hdr) {
  1316.     // 0000F0FF 12 bits    sync mark
  1317.     //
  1318.     // 00000800  1 bit    version
  1319.     // 00000600  2 bits    layer (3 = layer I, 2 = layer II, 1 = layer III)
  1320.     // 00000100  1 bit    error protection (0 = enabled)
  1321.     //
  1322.     // 00F00000  4 bits    bitrate_index
  1323.     // 000C0000  2 bits    sampling_freq
  1324.     // 00020000  1 bit    padding
  1325.     // 00010000  1 bit    extension
  1326.     //
  1327.     // C0000000  2 bits    mode (0=stereo, 1=joint stereo, 2=dual channel, 3=mono)
  1328.     // 30000000  2 bits    mode_ext
  1329.     // 08000000  1 bit    copyright
  1330.     // 04000000  1 bit    original
  1331.     // 03000000  2 bits    emphasis
  1332.  
  1333.     // 00 for layer ("layer 4") is not valid
  1334.     if (!(hdr & 0x00000600))
  1335.         return false;
  1336.  
  1337.     // 1111 for bitrate is not valid
  1338.     if ((hdr & 0x00F00000) == 0x00F00000)
  1339.         return false;
  1340.  
  1341.     // 11 for sampling frequency is not valid
  1342.     if ((hdr & 0x000C0000) == 0x000C0000)
  1343.         return false;
  1344.  
  1345.     // Looks okay to me...
  1346.     return true;
  1347. }
  1348.  
  1349. ////////////////////////////////////////////////////////////////////
  1350.  
  1351. class MPEGAudioParser {
  1352. private:
  1353.     unsigned long lFirstHeader;
  1354.     int hstate, skip;
  1355.     unsigned long header;
  1356.     MPEGSampleInfo msi;
  1357.     __int64 bytepos;
  1358.  
  1359. public:
  1360.     MPEGAudioParser();
  1361.  
  1362.     void Parse(const void *, int, DataVector *);
  1363.     unsigned long getHeader();
  1364. };
  1365.  
  1366. MPEGAudioParser::MPEGAudioParser() {
  1367.     lFirstHeader = 0;
  1368.     header = 0;
  1369.     hstate = 0;
  1370.     skip = 0;
  1371.     bytepos = 0;
  1372. }
  1373.  
  1374. unsigned long MPEGAudioParser::getHeader() {
  1375.     return lFirstHeader;
  1376. }
  1377.  
  1378. void MPEGAudioParser::Parse(const void *pData, int len, DataVector *dst) {
  1379.     unsigned char *src = (unsigned char *)pData;
  1380.  
  1381.     while(len>0) {
  1382.         if (skip) {
  1383.             int tc = skip;
  1384.  
  1385.             if (tc > len)
  1386.                 tc = len;
  1387.  
  1388.             len -= tc;
  1389.             skip -= tc;
  1390.             src += tc;
  1391.  
  1392.             // Audio frame finished?
  1393.  
  1394.             if (!skip) {
  1395.                 dst->Add(&msi);
  1396.             }
  1397.  
  1398.             continue;
  1399.         }
  1400.  
  1401.         // Collect header bytes.
  1402.  
  1403.         ++hstate;
  1404.         header = (header>>8) | ((long)*src++ << 24);
  1405.         --len;
  1406.  
  1407.         if (hstate>=4 && MPEG_check_audio_header_validity(header)) {
  1408.  
  1409.             // Check for header consistency.
  1410.             //
  1411.             // It conceivably could be possible for the stream to change, but
  1412.             // this is VERY unlikely.  Instead, we'll assume the bitrate,
  1413.             // sampling frequency, MPEG level/layer, mode, copyright, and
  1414.             // original flags do not change.
  1415.             //
  1416.             // 11/21:    EH_ED.MPG switches between stereo and joint_stereo mode
  1417.             //            in the middle of the audio stream.  Mode check disabled.
  1418.             //
  1419.             // 02/21/00: Hyper Police #3 switches original bits.
  1420.  
  1421.             if (lFirstHeader && ((header ^ lFirstHeader) & 0x08FC0E00)) {
  1422.                 continue;
  1423.             }
  1424.  
  1425.             // Okay, we like the header.
  1426.  
  1427.             hstate = 0;
  1428.  
  1429.             // Must be a frame start.
  1430.  
  1431.             if (!lFirstHeader)
  1432.                 lFirstHeader = header;
  1433.  
  1434.             long lFrameLen;
  1435.  
  1436.             // Layer I works in units of 4 bytes.  Layer II and III have byte granularity.
  1437.             // Both may or may not have one extra unit depending on the padding bit.
  1438.  
  1439.             int layer            = ((header>>9)&3)^3;
  1440.             int bitrateidx        = (header>>20)&15;
  1441.             int samprate        = samp_freq[(header>>18)&3];
  1442.             bool padding        = !!(header & 0x00020000);
  1443.  
  1444.             if (!layer) {    // layer I
  1445.                 lFrameLen = 4*((bitrate[layer][bitrateidx]*12000) / samprate);
  1446.                 if (padding) lFrameLen+=4;
  1447.             } else {                                                    // layer II, III
  1448.                 lFrameLen = (bitrate[layer][bitrateidx] * 144000) / samprate;
  1449.                 if (padding) ++lFrameLen;
  1450.             }
  1451.  
  1452.             // Setup the sample information.  Don't add the sample, in case it's incomplete.
  1453.  
  1454.             msi.stream_pos        = bytepos + (src - (unsigned char *)pData) - 4;
  1455.             msi.header            = header;
  1456.             msi.size            = lFrameLen;
  1457.  
  1458.             // Now skip the remainder of the sample.
  1459.  
  1460.             skip = lFrameLen-4;
  1461.         }
  1462.     }
  1463.  
  1464.     bytepos += src - (unsigned char *)pData;
  1465. }
  1466.  
  1467. //////////////////////////////////////////////////////////////////////////
  1468. //
  1469. //
  1470. //                    MPEGVideoParser
  1471. //
  1472. //
  1473. //////////////////////////////////////////////////////////////////////////
  1474.  
  1475. class MPEGVideoParser {
  1476. private:
  1477.     unsigned char buf[72+64];
  1478.     char nonintramatrix[64];
  1479.     char intramatrix[64];
  1480.  
  1481.     int idx, bytes;
  1482.  
  1483.     MPEGSampleInfo msi;
  1484.     __int64 bytepos;
  1485.     long header;
  1486.  
  1487.     bool fCustomIntra, fCustomNonintra;
  1488.     bool fPicturePending;
  1489.     bool fFoundSequenceStart;
  1490.  
  1491. public:
  1492.     long frame_rate;
  1493.     int width, height;
  1494.  
  1495.     MPEGVideoParser();
  1496.  
  1497.     void setPos(__int64);
  1498.     void Parse(const void *, int, DataVector *);
  1499. };
  1500.  
  1501. MPEGVideoParser::MPEGVideoParser() {
  1502.     bytepos = 0;
  1503.     header = -1;
  1504.  
  1505.     fCustomIntra = false;
  1506.     fCustomNonintra = false;
  1507.     fPicturePending = false;
  1508.     fFoundSequenceStart = false;
  1509.  
  1510.     idx = bytes = 0;
  1511. }
  1512.  
  1513. void MPEGVideoParser::setPos(__int64 pos) {
  1514.     bytepos = pos;
  1515. }
  1516.  
  1517. void MPEGVideoParser::Parse(const void *pData, int len, DataVector *dst) {
  1518.     static const long frame_speeds[16]={
  1519.         0,            // 0
  1520.         23976,        // 1 (23.976 fps) - FILM
  1521.         24000,        // 2 (24.000 fps)
  1522.         25000,        // 3 (25.000 fps) - PAL
  1523.         29970,        // 4 (29.970 fps) - NTSC
  1524.         30000,        // 5 (30.000 fps)
  1525.         50000,        // 6 (50.000 fps) - PAL noninterlaced
  1526.         59940,        // 7 (59.940 fps) - NTSC noninterlaced
  1527.         60000,        // 8 (60.000 fps)
  1528.         0,            // 9
  1529.         0,            // 10
  1530.         0,            // 11
  1531.         0,            // 12
  1532.         0,            // 13
  1533.         0,            // 14
  1534.         0            // 15
  1535.     };
  1536.  
  1537.     unsigned char *src = (unsigned char *)pData;
  1538.  
  1539.     while(len>0) {
  1540.         if (idx<bytes) {
  1541.             int tc = bytes - idx;
  1542.  
  1543.             if (tc > len)
  1544.                 tc = len;
  1545.  
  1546.             memcpy(buf+idx, src, tc);
  1547.  
  1548.             len -= tc;
  1549.             idx += tc;
  1550.             src += tc;
  1551.  
  1552.             // Finished?
  1553.  
  1554.             if (idx>=bytes) {
  1555.                 switch(header) {
  1556.                     case VIDPKT_TYPE_PICTURE_START:
  1557.                         msi.frame_type        = (buf[1]>>3)&7;
  1558.                         msi.subframe_num    = (buf[0]<<2) | (buf[1]>>6);
  1559.                         fPicturePending        = true;
  1560.                         header = 0xFFFFFFFF;
  1561.                         break;
  1562.  
  1563.                     case VIDPKT_TYPE_SEQUENCE_START:
  1564.                         //    12 bits: width
  1565.                         //    12 bits: height
  1566.                         //     4 bits: aspect ratio
  1567.                         //     4 bits: picture rate
  1568.                         //    18 bits: bitrate
  1569.                         //     1 bit : ?
  1570.                         //    10 bits: VBV buffer
  1571.                         //     1 bit : const_param
  1572.                         //     1 bit : intramatrix present
  1573.                         //[256 bits: intramatrix]
  1574.                         //     1 bit : nonintramatrix present
  1575.                         //[256 bits: nonintramatrix]
  1576.                         if (bytes == 8) {
  1577.                             width    = (buf[0]<<4) + (buf[1]>>4);
  1578.                             height    = ((buf[1]<<8)&0xf00) + buf[2];
  1579.                             frame_rate = frame_speeds[(unsigned char)buf[3] & 15];
  1580.  
  1581.                             if (!frame_rate)
  1582.                                 throw MyError("MPEG-1 video stream contains an invalid frame rate (%d).", buf[3] & 15);
  1583.  
  1584.                             if (buf[7]&2) {        // Intramatrix present
  1585.                                 bytes = 72;    // can't decide yet
  1586.                                 break;
  1587.                             } else if (buf[7]&1) {    // Nonintramatrix present
  1588.                                 bytes = 72;
  1589.                                 break;
  1590.                             }
  1591.                         } else if (bytes == 72) {
  1592.                             if (buf[7]&2) {
  1593.                                 for(int i=0; i<64; i++)
  1594.                                     intramatrix[i] = ((buf[i+7]<<7)&0x80) | (buf[i+8]>>1);
  1595.  
  1596.                                 fCustomIntra = true;
  1597.  
  1598.                                 if (buf[71]&1) {
  1599.                                     bytes = 72+64;        // both matrices
  1600.                                     break;
  1601.                                 }
  1602.                             } else {        // Nonintramatrix only
  1603.                                 memcpy(nonintramatrix, buf+8, 64);
  1604.                                 fCustomNonintra = true;
  1605.                             }
  1606.                         } else if (bytes == 72+64) {    // Both matrices (intra already loaded)
  1607.                             memcpy(nonintramatrix, buf+72, 64);
  1608.  
  1609.                             fCustomIntra = fCustomNonintra = true;
  1610.                         }
  1611.  
  1612.                         // Initialize MPEG-1 video decoder.
  1613.  
  1614.                         mpeg_initialize(width, height, fCustomIntra ? intramatrix : NULL, fCustomNonintra ? nonintramatrix : NULL, FALSE);
  1615.                         header = 0xFFFFFFFF;
  1616.                         break;
  1617.                 }    
  1618.             }
  1619.             continue;
  1620.         }
  1621.  
  1622.         // Look for a valid MPEG-1 header
  1623.  
  1624.         header = (header<<8) + *src++;
  1625.         --len;
  1626.  
  1627.         if ((header&0xffffff00) == 0x00000100) {
  1628.             header &= 0xff;
  1629.             if (fPicturePending && (header<VIDPKT_TYPE_SLICE_START_MIN || header>VIDPKT_TYPE_SLICE_START_MAX) && header != VIDPKT_TYPE_USER_START) {
  1630.                 msi.size = (int)(bytepos + (src - (unsigned char *)pData) - 4 - msi.stream_pos);
  1631.                 dst->Add(&msi);
  1632.                 fPicturePending = false;
  1633.             }
  1634.  
  1635.             switch(header) {
  1636.             case VIDPKT_TYPE_SEQUENCE_START:
  1637.                 if (fFoundSequenceStart) break;
  1638.                 fFoundSequenceStart = true;
  1639.  
  1640.                 bytes = 8;
  1641.                 idx = 0;
  1642.                 break;
  1643.  
  1644.             case VIDPKT_TYPE_PICTURE_START:
  1645.                 idx = 0;
  1646.                 bytes = 2;
  1647.                 msi.stream_pos = bytepos + (src - (unsigned char *)pData) - 4;
  1648.                 break;
  1649.  
  1650.             case VIDPKT_TYPE_EXT_START:
  1651.                 throw MyError("VirtualDub cannot decode MPEG-2 video streams.");
  1652.  
  1653.             default:
  1654.                 header = 0xFFFFFFFF;
  1655.             }
  1656.         }
  1657.     }
  1658.  
  1659.     bytepos += src - (unsigned char *)pData;
  1660. }
  1661.  
  1662. //////////////////////////////////////////////////////////////////////////
  1663. //
  1664. //
  1665. //                            InputFileMPEG
  1666. //
  1667. //
  1668. //////////////////////////////////////////////////////////////////////////
  1669.  
  1670.  
  1671. extern HWND g_hWnd;
  1672.  
  1673. const char InputFileMPEG::szME[]="MPEG Import Filter";
  1674.  
  1675. #define VIDEO_PACKET_BUFFER_SIZE    (1048576)
  1676. #define AUDIO_PACKET_BUFFER_SIZE    (65536)
  1677.  
  1678. InputFileMPEG::InputFileMPEG() {
  1679.     // clear variables
  1680.  
  1681.     file_cpos = 0;
  1682.     fh = -1;
  1683.     video_packet_buffer = NULL;
  1684.     audio_packet_buffer = NULL;
  1685.     video_packet_list = NULL;
  1686.     video_sample_list = NULL;
  1687.     audio_packet_list = NULL;
  1688.     audio_sample_list = NULL;
  1689.     audio_first_header = 0;
  1690.  
  1691.     audioSrc = NULL;
  1692.     videoSrc = NULL;
  1693.  
  1694.     fInterleaved = fHasAudio = FALSE;
  1695.  
  1696.     iDecodeMode = 0;
  1697.     fAcceptPartial = false;
  1698.     fAbort = false;
  1699.     fIsVCD = false;
  1700.  
  1701.     pFastRead = NULL;
  1702. }
  1703.  
  1704. InputFile *CreateInputFileMPEG() {
  1705.     return new InputFileMPEG();
  1706. }
  1707.  
  1708. void InputFileMPEG::Init(char *szFile) {
  1709.     BOOL finished = FALSE;
  1710.     HWND hWndStatus;
  1711.  
  1712.     AddFilename(szFile);
  1713.  
  1714.     // allocate packet buffer
  1715.  
  1716.     if (!(video_packet_buffer = new char[VIDEO_PACKET_BUFFER_SIZE]))
  1717.         throw MyMemoryError();
  1718.  
  1719. #ifdef ENABLE_AUDIO_SUPPORT
  1720.     if (!(audio_packet_buffer = new char[AUDIO_PACKET_BUFFER_SIZE]))
  1721.         throw MyMemoryError();
  1722. #endif
  1723.  
  1724.     // see if we can open the file
  1725.  
  1726.     if (-1 == (fh = _open(szFile, _O_BINARY | _O_RDONLY | _O_SEQUENTIAL)))
  1727.         throw MyError("%s: couldn't open \"%s\"", szME, szFile);
  1728.  
  1729.     pFastRead = new FastReadStream(fh, 24, 32768);
  1730.  
  1731.     // determine the file's size...
  1732.  
  1733.     if (-1 == (file_len = _filelengthi64(fh)))
  1734.         throw MyError("%s: couldn't determine file size", szME);
  1735.  
  1736.     // Begin file parsing!  This is a royal bitch!
  1737.  
  1738.     StartScan();
  1739.  
  1740.     try {
  1741.         DataVector video_stream_blocks(sizeof MPEGPacketInfo);
  1742.         DataVector video_stream_samples(sizeof MPEGSampleInfo);
  1743.         __int64 video_stream_pos = 0;
  1744.         MPEGVideoParser videoParser;
  1745.  
  1746.  
  1747. #ifdef ENABLE_AUDIO_SUPPORT
  1748.         DataVector audio_stream_blocks(sizeof MPEGPacketInfo);
  1749.         DataVector audio_stream_samples(sizeof MPEGSampleInfo);
  1750.         MPEGAudioParser audioParser;
  1751.         __int64 audio_stream_pos = 0;
  1752. #endif
  1753.  
  1754.         bool first_packet = true;
  1755.         bool end_of_file = false;
  1756.         bool fTrimLastOff = false;
  1757.  
  1758.         // seek to first pack code
  1759.  
  1760.         {
  1761.             char ch[3];
  1762.  
  1763.             _read(fh, ch, 3);
  1764.  
  1765.             if (ch[0]=='R' && ch[1]=='I' && ch[2]=='F') {
  1766.                 fIsVCD = true;
  1767.                 fInterleaved = true;
  1768.  
  1769.                 // The Read() code skips over the last 4 bytes of a sector
  1770.                 // and the beginning 16 bytes of the next, so we need to
  1771.                 // back up 4.
  1772.  
  1773.                 _lseeki64(fh, 40, SEEK_SET);
  1774.                 i64ScanCpos = 40;
  1775.             } else if (ch[0]==0 && ch[1]==0 && ch[2]==1) {
  1776.                 fIsVCD = false;
  1777.  
  1778.                 // We want reads to be aligned.
  1779.  
  1780.                 i64ScanCpos = 0;
  1781.                 _lseeki64(fh, 0, SEEK_SET);
  1782.                 Skip(3);
  1783.             } else
  1784.                 throw MyError("%s: Invalid MPEG file", szME);
  1785.         }
  1786.  
  1787.         try {
  1788.             do {
  1789.                 int c;
  1790.                 int stream_id, pack_length;
  1791.  
  1792.                 file_cpos = Tell();
  1793.                 guiDlgMessageLoop(hWndStatus);
  1794.  
  1795.                 if (fAbort)
  1796.                     throw MyUserAbortError();
  1797.  
  1798.                 if (first_packet) {
  1799.                     if (!fIsVCD) {
  1800.                         c = Read();
  1801.  
  1802.                         fInterleaved = (c==0xBA);
  1803.  
  1804.                         if (!fInterleaved) {
  1805.                             videoParser.setPos(Tell()-4);
  1806.  
  1807.                             unsigned char buf[4];
  1808.  
  1809.                             buf[0] = buf[1] = 0;
  1810.                             buf[2] = 1;
  1811.                             buf[3] = c;
  1812.  
  1813.                             videoParser.Parse(buf, 4, &video_stream_samples);
  1814.                         }
  1815.                     }
  1816.  
  1817.                     // pop up the dialog...
  1818.  
  1819.                     if (!(hWndStatus = CreateDialogParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_PROGRESS), g_hWnd, ParseDialogProc, (LPARAM)this)))
  1820.                         throw MyMemoryError();
  1821.  
  1822.                     first_packet = false;
  1823.                 } else if (fInterleaved)
  1824.                     c=Read();
  1825.                 else
  1826.                     c = 0xe0;
  1827.  
  1828.                 switch(c) {
  1829.  
  1830. //                    One for audio and for video?
  1831.  
  1832.                     case VIDPKT_TYPE_SEQUENCE_END:
  1833.                     case 0xb9:        // ISO 11172 end code
  1834.                         break;
  1835.  
  1836.                     case 0xba:        // new pack
  1837.                         if ((Read() & 0xf0) != 0x20) throw MyError("%s: pack synchronization error", szME);
  1838.                         Skip(7);
  1839.                         break;
  1840.  
  1841.                     case 0xbb:        // system header
  1842.                         Skip(8);
  1843.                         while((c=Read()) & 0x80)
  1844.                             Skip(2);
  1845.  
  1846.                         UnRead();
  1847.                         break;
  1848.  
  1849.                     default:
  1850.                         if (c < 0xc0 || c>=0xf0)
  1851.                             break;
  1852.  
  1853.                         if (fInterleaved) {
  1854.                             __int64 tagpos = Tell();
  1855.                             stream_id = c;
  1856.                             pack_length = Read()<<8;
  1857.                             pack_length += Read();
  1858.  
  1859. //                            _RPT3(0,"Encountered packet: stream %02x, pack length %ld, position %08lx\n", stream_id, pack_length, file_cpos);
  1860.  
  1861.                             if (stream_id != PRIVATE_STREAM2) {
  1862.                                 --pack_length;
  1863.  
  1864.                                 while((c=Read()) == 0xff) {
  1865.                                     --pack_length;
  1866.                                 }
  1867.  
  1868.                                 if ((c>>6) == 1) {    // 01
  1869.                                     pack_length-=2;
  1870.                                     Read();            // skip one byte
  1871.                                     c=Read();
  1872.                                 }
  1873.                                 if ((c>>4) == 2) {    // 0010
  1874.                                     pack_length -= 4;
  1875.                                     Skip(4);
  1876.                                 } else if ((c>>4) == 3) {    // 0011
  1877.                                     pack_length -= 9;
  1878.                                     Skip(9);
  1879.                                 } else if (c != 0x0f)
  1880.                                     throw MyError("%s: packet sync error on packet stream (%I64x)", szME, tagpos);
  1881.                             }
  1882.                         } else {
  1883.                             stream_id = 0xe0;
  1884.                             pack_length = 65536; //VIDEO_PACKET_BUFFER_SIZE;
  1885.                         }
  1886.  
  1887.                         // check packet type
  1888.  
  1889.                         if ((0xe0 & stream_id) == 0xc0) {            // audio packet
  1890.  
  1891. #ifdef ENABLE_AUDIO_SUPPORT
  1892.                             fHasAudio = TRUE;
  1893.  
  1894.                             MPEGPacketInfo mpi;
  1895.  
  1896.                             mpi.file_pos        = Tell();
  1897.                             mpi.stream_pos        = audio_stream_pos;
  1898.                             audio_stream_blocks.Add(&mpi);
  1899.                             audio_stream_pos += pack_length;
  1900.  
  1901.                             Read(audio_packet_buffer, pack_length, false);
  1902.                             audioParser.Parse(audio_packet_buffer, pack_length, &audio_stream_samples);
  1903.                             pack_length = 0;
  1904. #endif    // ENABLE_AUDIO_SUPPORT
  1905.  
  1906.                         } else if ((0xf0 & stream_id) == 0xe0) {    // video packet
  1907.  
  1908.                             if (fInterleaved) {
  1909.                                 MPEGPacketInfo mpi;
  1910.  
  1911.                                 mpi.file_pos        = Tell();
  1912.                                 mpi.stream_pos        = video_stream_pos;
  1913.                                 video_stream_blocks.Add(&mpi);
  1914.                                 video_stream_pos += pack_length;
  1915.                             }
  1916.  
  1917.                             int actual = Read(video_packet_buffer, pack_length, !fInterleaved);
  1918.  
  1919.                             if (!fInterleaved && actual < pack_length)
  1920.                                 end_of_file = true;
  1921.  
  1922.                             videoParser.Parse(video_packet_buffer, actual, &video_stream_samples);
  1923.                             pack_length = 0;
  1924.                         }
  1925.  
  1926.                         if (pack_length)
  1927.                                 Skip(pack_length);
  1928.                         break;
  1929.                 }
  1930.             } while(!finished && (fInterleaved ? NextStartCode() : !end_of_file));
  1931.         } catch(MyError) {
  1932.             if (!fAcceptPartial)
  1933.                 throw;
  1934.  
  1935.             fTrimLastOff = true;
  1936.         }
  1937.  
  1938.         // We're done scanning the file.  Finish off any ending packets we may have.
  1939.  
  1940.         static const unsigned char finish_tag[]={ 0, 0, 1, 0xff };
  1941.  
  1942.         videoParser.Parse(finish_tag, 4, &video_stream_samples);
  1943.  
  1944.         this->width = videoParser.width;
  1945.         this->height = videoParser.height;
  1946.         this->frame_rate = videoParser.frame_rate;
  1947.  
  1948.         // Construct stream and packet lookup tables.
  1949.  
  1950.         if (fInterleaved) {
  1951.             MPEGPacketInfo mpi;
  1952.  
  1953.             mpi.file_pos        = 0;
  1954.             mpi.stream_pos        = video_stream_pos;
  1955.             video_stream_blocks.Add(&mpi);
  1956.  
  1957.             video_packet_list = (MPEGPacketInfo *)video_stream_blocks.MakeArray();
  1958.             packets = video_stream_blocks.Length() - 1;
  1959.  
  1960. #ifdef ENABLE_AUDIO_SUPPORT
  1961.             mpi.file_pos        = 0;
  1962.             mpi.stream_pos        = audio_stream_pos;
  1963.             audio_stream_blocks.Add(&mpi);
  1964.  
  1965.             audio_packet_list = (MPEGPacketInfo *)audio_stream_blocks.MakeArray();
  1966.             apackets = audio_stream_blocks.Length() - 1;
  1967.  
  1968.             audio_sample_list = (MPEGSampleInfo *)audio_stream_samples.MakeArray();
  1969.             aframes = audio_stream_samples.Length();
  1970.             audio_first_header = audioParser.getHeader();
  1971. #endif // ENABLE_AUDIO_SUPPORT
  1972.         }
  1973.  
  1974.         video_sample_list = (MPEGSampleInfo *)video_stream_samples.MakeArray();
  1975.         frames = video_stream_samples.Length();
  1976.  
  1977.         // Begin renumbering the frames.  Some MPEG files have incorrectly numbered
  1978.         // subframes within each group.  So we do them from scratch.
  1979.  
  1980.         {
  1981.             int i;
  1982.             int sf = 0;        // subframe #
  1983.             MPEGSampleInfo *cached_IP = NULL;
  1984.  
  1985.             for(i=0; i<frames; i++) {
  1986.  
  1987. //                _RPT3(0,"Frame #%d: %c-frame (subframe: %d)\n", i, video_sample_list[i].frame_type[" IPBD567"], video_sample_list[i].subframe_num);
  1988.  
  1989.                 if (video_sample_list[i].frame_type != MPEG_FRAME_TYPE_B) {
  1990.                     if (cached_IP) cached_IP->subframe_num = sf++;
  1991.                     cached_IP = &video_sample_list[i];
  1992.  
  1993.                     if (video_sample_list[i].frame_type == MPEG_FRAME_TYPE_I)
  1994.                         sf = 0;
  1995.                 } else
  1996.                     video_sample_list[i].subframe_num = sf++;
  1997.  
  1998. //                _RPT3(0,"Frame #%d: %c-frame (subframe: %d)\n", i, video_sample_list[i].frame_type[" IPBD567"], video_sample_list[i].subframe_num);
  1999.             }
  2000.  
  2001.             if (cached_IP)
  2002.                 cached_IP->subframe_num = sf;
  2003.         }
  2004.  
  2005.         // If we are accepting partial streams, then cut off the last video frame, as it may be incomplete.
  2006.         // The audio parser checks for the entire frame to arrive, so we don't need to trim the audio.
  2007.  
  2008.         if (fTrimLastOff) {
  2009.             if (frames) --frames;
  2010.         }
  2011.  
  2012.     } catch(MyError e) {
  2013.         DestroyWindow(hWndStatus);
  2014.         hWndStatus = NULL;
  2015.         throw e;
  2016.     }
  2017.  
  2018.     EndScan();
  2019.  
  2020.     DestroyWindow(hWndStatus);
  2021.     hWndStatus = NULL;
  2022.  
  2023.     // initialize DubSource pointers
  2024.  
  2025. #ifdef ENABLE_AUDIO_SUPPORT
  2026.     audioSrc = fHasAudio ? new AudioSourceMPEG(this) : NULL;
  2027.     if (audioSrc)
  2028.         audioSrc->init();
  2029. #endif
  2030.  
  2031.     videoSrc = new VideoSourceMPEG(this);
  2032.     videoSrc->init();
  2033. }
  2034.  
  2035. InputFileMPEG::~InputFileMPEG() {
  2036.     _RPT0(0,"Destructor called\n");
  2037.  
  2038.     EndScan();
  2039.  
  2040.     delete videoSrc;
  2041.     delete audioSrc;
  2042.  
  2043.     mpeg_deinitialize();
  2044.     delete video_packet_buffer;
  2045.     delete audio_packet_buffer;
  2046.     delete video_packet_list;
  2047.     delete video_sample_list;
  2048.     delete audio_packet_list;
  2049.     delete audio_sample_list;
  2050.  
  2051.     if (pFastRead)
  2052.         delete pFastRead;
  2053.  
  2054.     if (fh >= 0)
  2055.         _close(fh);
  2056. }
  2057.  
  2058. void InputFileMPEG::StartScan() {
  2059.     if (!(pScanBuffer = new char[SCAN_BUFFER_SIZE]))
  2060.         throw MyMemoryError();
  2061.  
  2062.     pScan = pScanLimit = pScanBuffer;
  2063.     i64ScanCpos = 0;
  2064. }
  2065.  
  2066. void InputFileMPEG::EndScan() {
  2067.     delete pScanBuffer;
  2068.     pScanBuffer = NULL;
  2069. }
  2070.  
  2071. bool InputFileMPEG::NextStartCode() {
  2072.     int c;
  2073.  
  2074.     while(EOF!=(c=Read())) {
  2075.         if (!c) {    // 00
  2076.             if (EOF==(c=Read())) return false;
  2077.  
  2078.             if (!c) {    // 00 00
  2079.                 do {
  2080.                     if (EOF==(c=Read())) return false;
  2081.                 } while(!c);
  2082.  
  2083.                 if (c==1)    // (00 00 ...) 00 00 01 xx
  2084.                     return true;
  2085.             }
  2086.         }
  2087.     }
  2088.  
  2089.     return false;
  2090. }
  2091.  
  2092. void InputFileMPEG::Skip(int bytes) {
  2093.     int tc;
  2094.  
  2095.     while(bytes>0) {
  2096.         tc = pScanLimit - pScan;
  2097.  
  2098.         if (!tc) {
  2099.             if (EOF == _Read())
  2100.                 throw MyError("%s: unexpected end of file", szME);
  2101.  
  2102.             --bytes;
  2103.             continue;
  2104.         }
  2105.             
  2106.  
  2107.         if (tc >= bytes) {
  2108.             pScan += bytes;
  2109.             break;
  2110.         }
  2111.  
  2112.         bytes -= tc;
  2113.         i64ScanCpos += (pScanLimit - pScanBuffer);
  2114.         pScan = pScanLimit = pScanBuffer;
  2115.     }
  2116. }
  2117.  
  2118. int InputFileMPEG::_Read() {
  2119.     char c;
  2120.  
  2121.     if (!pScan)
  2122.         return EOF;
  2123.  
  2124.     if (!Read(&c, 1, true))
  2125.         return EOF;
  2126.  
  2127.     return (unsigned char)c;
  2128. }
  2129.  
  2130. int InputFileMPEG::Read(void *buffer, int bytes, bool fShortOkay) {
  2131.     int total = 0;
  2132.     int tc;
  2133.  
  2134.     if (!pScan)
  2135.         if (fShortOkay)
  2136.             return 0;
  2137.         else
  2138.             throw MyError("%s: unexpected end of file", szME);
  2139.  
  2140.     if (pScan < pScanLimit) {
  2141.         tc = pScanLimit - pScan;
  2142.  
  2143.         if (tc > bytes)
  2144.             tc = bytes;
  2145.  
  2146.         memcpy(buffer, pScan, tc);
  2147.  
  2148.         pScan += tc;
  2149.         buffer = (char *)buffer + tc;
  2150.         total = tc;
  2151.         bytes -= tc;
  2152.     }
  2153.  
  2154.     if (bytes) {
  2155.         int actual;
  2156.  
  2157.         // Split the read into SCAN_BUFFER_SIZE chunks so we can
  2158.         // keep reading big chunks throughout the file.
  2159.  
  2160.         tc = bytes - bytes % SCAN_BUFFER_SIZE;
  2161.  
  2162.         // With a VideoCD, read the header and then the pack.
  2163.  
  2164.         _RPT1(0,"Starting at %I64lx\n", _telli64(fh));
  2165.  
  2166.         if (tc) do {
  2167.             if (fIsVCD) {
  2168.                 char hdr[20];
  2169.  
  2170.                 actual = _read(fh, hdr, 20);
  2171.  
  2172.                 if (actual < 0)
  2173.                     throw MyError("%s: read error", szME);
  2174.                 else if (actual != 20)
  2175.                     if (fShortOkay)
  2176.                         return total;
  2177.  
  2178.                 i64ScanCpos += 20;
  2179.  
  2180.                 tc = 2332;
  2181.             }
  2182.  
  2183.             if (tc > 0) {
  2184.                 actual = _read(fh, buffer, tc);
  2185.  
  2186.                 if (actual < 0)
  2187.                     throw MyError("%s: read error", szME);
  2188.                 else if (actual != tc)
  2189.                     if (fShortOkay)
  2190.                         return total + actual;
  2191.                     else
  2192.                         throw MyError("%s: unexpected end of file", szME);
  2193.  
  2194.                 total += actual;
  2195.                 i64ScanCpos += actual;
  2196.                 buffer = (char *)buffer + actual;
  2197.             }
  2198.  
  2199.             bytes -= tc;
  2200.         } while(fIsVCD && bytes >= 2332);
  2201.  
  2202.         tc = bytes;
  2203.  
  2204.         if (tc) {
  2205.             if (fIsVCD) {
  2206.                 char hdr[20];
  2207.  
  2208.                 actual = _read(fh, hdr, 20);
  2209.  
  2210.                 if (actual < 0)
  2211.                     throw MyError("%s: read error", szME);
  2212.                 else if (actual != 20)
  2213.                     if (fShortOkay)
  2214.                         return total;
  2215.  
  2216.                 i64ScanCpos += 20;
  2217.  
  2218.                 actual = _read(fh, pScanBuffer, 2332);
  2219.             } else
  2220.                 actual = _read(fh, pScanBuffer, SCAN_BUFFER_SIZE);
  2221.  
  2222.             if (actual < 0)
  2223.                 throw MyError("%s: read error", szME);
  2224.             else if (!fShortOkay && actual < tc)
  2225.                 throw MyError("%s: unexpected end of file", szME);
  2226.  
  2227.             i64ScanCpos += (pScan - pScanBuffer);
  2228.  
  2229.             if (actual < tc)
  2230.                 tc = actual;
  2231.  
  2232.             memcpy(buffer, pScanBuffer, tc);
  2233.  
  2234.             total += tc;
  2235.  
  2236.             pScanLimit    = pScanBuffer + actual;
  2237.             pScan        = pScanBuffer + tc;
  2238.         }
  2239.     }
  2240.  
  2241.     return total;
  2242. }
  2243.  
  2244. __int64 InputFileMPEG::Tell() {
  2245.     return i64ScanCpos + (pScan - pScanBuffer);
  2246. }
  2247.  
  2248. //////////////////////
  2249.  
  2250. void InputFileMPEG::ReadStream(void *buffer, __int64 pos, long len, bool fAudio) {
  2251.     int pkt = 0;
  2252.     long delta;
  2253.     char *ptr = (char *)buffer;
  2254.     MPEGPacketInfo *packet_list = fAudio ? audio_packet_list : video_packet_list;
  2255.     int pkts = fAudio ? apackets : packets;
  2256.  
  2257. //    _RPT2(0,"Stream read request: pos %ld, len %ld\n", pos, len);
  2258.  
  2259.     if (!fInterleaved) {
  2260.  
  2261.         if (pFastRead)
  2262.             pFastRead->Read(0, pos, buffer, len);
  2263.         else {
  2264.             if (_lseeki64(fh, pos, SEEK_SET)<0) throw MyError("seek error");
  2265.             if (len != _read(fh, buffer, len)) throw MyError("read error");
  2266.         }
  2267.         return;
  2268.     }
  2269.  
  2270.     // find the packet containing the data start using a binary search
  2271.  
  2272.     do {
  2273.         int l = 0;
  2274.         int r = pkts-1;
  2275.  
  2276.         // Check current packet
  2277.  
  2278.         pkt = last_packet[fAudio?1:0];
  2279.  
  2280.         if (pkt>=0 && pkt<pkts) {
  2281.             if (pos < packet_list[pkt].stream_pos)
  2282.                 r = pkt-1;
  2283.             else if (pos < packet_list[pkt+1].stream_pos)
  2284.                 break;
  2285.             else if (pkt+1 < pkts && pos < packet_list[pkt+2].stream_pos) {
  2286.                 ++pkt;
  2287.                 break;
  2288.             } else
  2289.                 l = pkt+2;
  2290.         }
  2291.  
  2292.         for(;;) {
  2293.             if (l > r) {
  2294.                 pkt = l;
  2295.                 break;
  2296.             }
  2297.  
  2298.             pkt = (l+r)/2;
  2299.  
  2300.             if (pos < packet_list[pkt].stream_pos)
  2301.                 r = pkt-1;
  2302.             else if (pos >= packet_list[pkt+1].stream_pos)
  2303.                 l = pkt+1;
  2304.             else
  2305.                 break;
  2306.         }
  2307.  
  2308.         if (pkt<0 || pkt >= pkts) throw MyError("MPEG Internal error: Invalid stream read position (%ld)", pos);
  2309.  
  2310.     } while(false);
  2311.  
  2312.     delta = (long)(pos - packet_list[pkt].stream_pos);
  2313.  
  2314.     // read data from packets
  2315.  
  2316.     while(len) {
  2317.         if (pkt >= pkts) throw MyError("Attempt to read past end of stream (pos %ld)", pos);
  2318.  
  2319.         long tc = (long)((packet_list[pkt+1].stream_pos - packet_list[pkt].stream_pos) - delta);
  2320.  
  2321.         if (tc>len) tc=len;
  2322.  
  2323. //        _RPT3(0,"Reading %ld bytes at %08lx+%ld\n", tc, video_packet_list[pkt].file_pos,delta);
  2324.  
  2325.         if (pFastRead) {
  2326.             pFastRead->Read(fAudio ? 1 : 0, packet_list[pkt].file_pos + delta, ptr, tc);
  2327.         } else {
  2328.             if (_lseeki64(fh, packet_list[pkt].file_pos + delta, SEEK_SET)<0)
  2329.                 throw MyError("seek error");
  2330.  
  2331.             if (tc!=_read(fh, ptr, tc)) throw MyError("read error");
  2332.         }
  2333.  
  2334.         len -= tc;
  2335.         ptr += tc;
  2336.         ++pkt;
  2337.         delta = 0;
  2338.     }
  2339.  
  2340.     last_packet[fAudio?1:0] = pkt-1;
  2341. }
  2342.  
  2343. BOOL CALLBACK InputFileMPEG::ParseDialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  2344.     InputFileMPEG *thisPtr = (InputFileMPEG *)GetWindowLong(hDlg, DWL_USER);
  2345.  
  2346.     switch(uMsg) {
  2347.     case WM_INITDIALOG:
  2348.         SetWindowLong(hDlg, DWL_USER, lParam);
  2349.         thisPtr = (InputFileMPEG *)lParam;
  2350.  
  2351.         SendMessage(hDlg, WM_SETTEXT, 0, (LPARAM)"MPEG Import Filter");
  2352.         SetDlgItemText(hDlg, IDC_STATIC_MESSAGE,
  2353.             thisPtr->fIsVCD
  2354.                 ? "Parsing VideoCD stream"
  2355.                 : thisPtr->fInterleaved ? "Parsing interleaved MPEG file" : "Parsing MPEG video file");
  2356.         SendMessage(GetDlgItem(hDlg, IDC_PROGRESS), PBM_SETRANGE, 0, MAKELPARAM(0, 16384));
  2357.         SetTimer(hDlg, 1, 250, (TIMERPROC)NULL);
  2358.         return TRUE;
  2359.  
  2360.     case WM_TIMER:
  2361.         {
  2362.             char buf[128];
  2363.         
  2364.             SendMessage(GetDlgItem(hDlg, IDC_PROGRESS), PBM_SETPOS, (WPARAM)((thisPtr->file_cpos*16384) / thisPtr->file_len), 0);
  2365.  
  2366.             if (thisPtr->fIsVCD)
  2367.                 wsprintf(buf, "%ld of %ld sectors", (long)(thisPtr->file_cpos/2352), (long)(thisPtr->file_len/2352));
  2368.             else
  2369.                 wsprintf(buf, "%ldK of %ldK", (long)(thisPtr->file_cpos>>10), (long)((thisPtr->file_len+1023)>>10));
  2370.  
  2371.             SendDlgItemMessage(hDlg, IDC_CURRENT_VALUE, WM_SETTEXT, 0, (LPARAM)buf);
  2372.         }
  2373.         return TRUE;
  2374.  
  2375.     case WM_COMMAND:
  2376.         if (LOWORD(wParam) == IDCANCEL)
  2377.             thisPtr->fAbort = true;
  2378.         return TRUE;
  2379.     }
  2380.  
  2381.     return 0;
  2382. }
  2383.  
  2384. ///////////////////////////////////////////////////////////////////////////
  2385.  
  2386. void InputFileMPEG::setOptions(InputFileOptions *_ifo) {
  2387.     InputFileMPEGOptions *ifo = (InputFileMPEGOptions *)_ifo;
  2388.  
  2389.     iDecodeMode = ifo->opts.iDecodeMode;
  2390.     fAcceptPartial = ifo->opts.fAcceptPartial;
  2391.  
  2392.     if (iDecodeMode & InputFileMPEGOptions::DECODE_NO_P)
  2393.         iDecodeMode |= InputFileMPEGOptions::DECODE_NO_B;
  2394. }
  2395.  
  2396. InputFileOptions *InputFileMPEG::createOptions(const char *buf) {
  2397.     InputFileMPEGOptions *ifo = new InputFileMPEGOptions();
  2398.  
  2399.     if (!ifo) throw MyMemoryError();
  2400.  
  2401.     if (!ifo->read(buf)) {
  2402.         delete ifo;
  2403.         return NULL;
  2404.     }
  2405.  
  2406.     return ifo;
  2407. }
  2408.  
  2409. InputFileOptions *InputFileMPEG::promptForOptions(HWND hwnd) {
  2410.     InputFileMPEGOptions *ifo = new InputFileMPEGOptions();
  2411.  
  2412.     if (!ifo) throw MyMemoryError();
  2413.  
  2414.     DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_EXTOPENOPTS_MPEG), hwnd, InputFileMPEGOptions::SetupDlgProc, (LPARAM)ifo);
  2415.  
  2416.     return ifo;
  2417. }
  2418.  
  2419. ///////////////////////////////////////////////////////////////////////////
  2420.  
  2421. typedef struct MyFileInfo {
  2422.     InputFileMPEG *thisPtr;
  2423.  
  2424.     volatile HWND hWndAbort;
  2425.     UINT statTimer;
  2426.  
  2427.     long lFrames;
  2428.     long lTotalSize;
  2429.     long lFrameCnt[3];
  2430.     long lFrameMinSize[3];
  2431.     long lFrameMaxSize[3];
  2432.     long lFrameTotalSize[3];
  2433.     long lAudioSize;
  2434.     long lAudioAvgBitrate;
  2435.     const char *lpszAudioMode;
  2436.  
  2437. } MyFileInfo;
  2438.  
  2439. void InputFileMPEG::_InfoDlgThread(void *pvInfo) {
  2440.     MyFileInfo *pInfo = (MyFileInfo *)pvInfo;
  2441.     InputFileMPEG *thisPtr = pInfo->thisPtr;
  2442.     long i;
  2443.     VideoSourceMPEG *vSrc = (VideoSourceMPEG *)pInfo->thisPtr->videoSrc;
  2444.     AudioSourceMPEG *aSrc = (AudioSourceMPEG *)pInfo->thisPtr->audioSrc;
  2445.     MPEGSampleInfo *msi;
  2446.  
  2447.     for(i=0; i<3; i++)
  2448.         pInfo->lFrameMinSize[i] = 0x7FFFFFFF;
  2449.  
  2450.     msi = thisPtr->video_sample_list;
  2451.     for(i = vSrc->lSampleFirst; i < vSrc->lSampleLast; ++i) {
  2452.         int iFrameType = msi->frame_type;
  2453.  
  2454.         if (iFrameType) {
  2455.             long lSize = msi->size;
  2456.             --iFrameType;
  2457.  
  2458.             ++pInfo->lFrameCnt[iFrameType];
  2459.             pInfo->lFrameTotalSize[iFrameType] += lSize;
  2460.  
  2461.             if (lSize < pInfo->lFrameMinSize[iFrameType])
  2462.                 pInfo->lFrameMinSize[iFrameType] = lSize;
  2463.  
  2464.             if (lSize > pInfo->lFrameMaxSize[iFrameType])
  2465.                 pInfo->lFrameMaxSize[iFrameType] = lSize;
  2466.  
  2467.             pInfo->lTotalSize += lSize;
  2468.  
  2469.         }
  2470.         ++pInfo->lFrames;
  2471.  
  2472.         ++msi;
  2473.         if (pInfo->hWndAbort) {
  2474.             SendMessage(pInfo->hWndAbort, WM_USER+256, 0, 0);
  2475.             return;
  2476.         }
  2477.     }
  2478.  
  2479.     ///////////////////////////////////////////////////////////////////////
  2480.  
  2481.     if (aSrc) {
  2482.         static const char *szModes[4]={ "stereo", "joint stereo", "dual channel", "mono" };
  2483.         bool fAudioMixedMode = false;
  2484.         bool fAudioMono = false;
  2485.         long lTotalBitrate = 0;
  2486.  
  2487.         msi = thisPtr->audio_sample_list;
  2488.  
  2489.         for(i = 0; i < thisPtr->aframes; ++i) {
  2490.             long fAudioHeader = msi->header;
  2491.  
  2492.             if ((thisPtr->audio_first_header ^ fAudioHeader) & MPEGAHDR_MODE_MASK)
  2493.                 fAudioMixedMode = true;
  2494.  
  2495.             // mode==3 is mono, all others are stereo
  2496.  
  2497.             if (!(~thisPtr->audio_first_header & MPEGAHDR_MODE_MASK))
  2498.                 fAudioMono = true;
  2499.  
  2500.             lTotalBitrate += bitrate[3-((fAudioHeader>>9)&3)][(fAudioHeader>>20)&15];
  2501.  
  2502.             pInfo->lAudioSize += msi->size;
  2503.  
  2504.             ++msi;
  2505.             if (pInfo->hWndAbort) {
  2506.                 SendMessage(pInfo->hWndAbort, WM_USER+256, 0, 0);
  2507.                 return;
  2508.             }
  2509.         }
  2510.  
  2511.         pInfo->lAudioAvgBitrate = lTotalBitrate / thisPtr->aframes;
  2512.  
  2513.         if (fAudioMixedMode) {
  2514.             if (fAudioMono)
  2515.                 pInfo->lpszAudioMode = "mixed mode";
  2516.             else
  2517.                 pInfo->lpszAudioMode = "mixed stereo";
  2518.         } else
  2519.             pInfo->lpszAudioMode = szModes[(thisPtr->audio_first_header>>30) & 3];
  2520.     }
  2521.  
  2522.     pInfo->hWndAbort = (HWND)1;
  2523. }
  2524.  
  2525. BOOL APIENTRY InputFileMPEG::_InfoDlgProc( HWND hDlg, UINT message, UINT wParam, LONG lParam) {
  2526.     MyFileInfo *pInfo = (MyFileInfo *)GetWindowLong(hDlg, DWL_USER);
  2527.     InputFileMPEG *thisPtr;
  2528.  
  2529.     if (pInfo)
  2530.         thisPtr = pInfo->thisPtr;
  2531.  
  2532.     switch (message)
  2533.     {
  2534.         case WM_INITDIALOG:
  2535.             SetWindowLong(hDlg, DWL_USER, lParam);
  2536.             pInfo = (MyFileInfo *)lParam;
  2537.             thisPtr = pInfo->thisPtr;
  2538.  
  2539.             if (thisPtr->videoSrc) {
  2540.                 char *s;
  2541.  
  2542.                 sprintf(g_msgBuf, "%dx%d, %.3f fps (%ld ╡s)",
  2543.                             thisPtr->width,
  2544.                             thisPtr->height,
  2545.                             (float)thisPtr->videoSrc->streamInfo.dwRate / thisPtr->videoSrc->streamInfo.dwScale,
  2546.                             MulDiv(thisPtr->videoSrc->streamInfo.dwScale, 1000000L, thisPtr->videoSrc->streamInfo.dwRate));
  2547.                 SetDlgItemText(hDlg, IDC_VIDEO_FORMAT, g_msgBuf);
  2548.  
  2549.                 s = g_msgBuf + sprintf(g_msgBuf, "%ld (", thisPtr->videoSrc->streamInfo.dwLength);
  2550.                 ticks_to_str(s, MulDiv(1000L*thisPtr->videoSrc->streamInfo.dwLength, thisPtr->videoSrc->streamInfo.dwScale, thisPtr->videoSrc->streamInfo.dwRate));
  2551.                 strcat(s,")");
  2552.                 SetDlgItemText(hDlg, IDC_VIDEO_NUMFRAMES, g_msgBuf);
  2553.             }
  2554.             if (thisPtr->audioSrc) {
  2555.                 WAVEFORMATEX *fmt = thisPtr->audioSrc->getWaveFormat();
  2556.  
  2557.                 sprintf(g_msgBuf, "%ldHz, %s", fmt->nSamplesPerSec, fmt->nChannels>1 ? "Stereo" : "Mono");
  2558.                 SetDlgItemText(hDlg, IDC_AUDIO_FORMAT, g_msgBuf);
  2559.  
  2560.                 sprintf(g_msgBuf, "%ld", thisPtr->aframes);
  2561.                 SetDlgItemText(hDlg, IDC_AUDIO_NUMFRAMES, g_msgBuf);
  2562.             }
  2563.  
  2564.             _beginthread(_InfoDlgThread, 10000, pInfo);
  2565.  
  2566.             pInfo->statTimer = SetTimer(hDlg, 1, 250, NULL);
  2567.  
  2568.             return (TRUE);
  2569.  
  2570.         case WM_COMMAND:                      
  2571.             if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
  2572.             {
  2573.                 if (pInfo->hWndAbort == (HWND)1)
  2574.                     EndDialog(hDlg, TRUE);  
  2575.                 return TRUE;
  2576.             }
  2577.             break;
  2578.  
  2579.         case WM_DESTROY:
  2580.             if (pInfo->statTimer) KillTimer(hDlg, pInfo->statTimer);
  2581.             break;
  2582.  
  2583.         case WM_TIMER:
  2584.             _RPT0(0,"timer hit\n");
  2585.             sprintf(g_msgBuf, "%ld", pInfo->lFrames);
  2586.             SetDlgItemText(hDlg, IDC_VIDEO_NUMKEYFRAMES, g_msgBuf);
  2587.  
  2588.             sprintf(g_msgBuf, "%ld / %ld / %ld", pInfo->lFrameCnt[0], pInfo->lFrameCnt[1], pInfo->lFrameCnt[2]);
  2589.             SetDlgItemText(hDlg, IDC_VIDEO_FRAMETYPECNT, g_msgBuf);
  2590.  
  2591.             {
  2592.                 int i;
  2593.  
  2594.                 UINT uiCtlIds[]={ IDC_VIDEO_IFRAMES, IDC_VIDEO_PFRAMES, IDC_VIDEO_BFRAMES };
  2595.  
  2596.                 for(i=0; i<3; i++) {
  2597.  
  2598.                     if (pInfo->lFrameCnt[i])
  2599.                         sprintf(g_msgBuf, "%ld / %ld / %ld (%ldK)"
  2600.                                     ,pInfo->lFrameMinSize[i]
  2601.                                     ,pInfo->lFrameTotalSize[i]/pInfo->lFrameCnt[i]
  2602.                                     ,pInfo->lFrameMaxSize[i]
  2603.                                     ,(pInfo->lFrameTotalSize[i]+1023)>>10);
  2604.                     else
  2605.                         sprintf(g_msgBuf,"(no %c-frames)", "IPB"[i]);
  2606.  
  2607.                     SetDlgItemText(hDlg, uiCtlIds[i], g_msgBuf);
  2608.                 }
  2609.  
  2610.             }
  2611.  
  2612.             if (pInfo->lTotalSize) {
  2613.                 long lBytesPerSec;
  2614.  
  2615.                 // bits * (frames/sec) / frames = bits/sec
  2616.  
  2617.                 lBytesPerSec = (long)((pInfo->lTotalSize * ((double)thisPtr->videoSrc->streamInfo.dwRate / thisPtr->videoSrc->streamInfo.dwScale)) / pInfo->lFrames + 0.5);
  2618.  
  2619.                 sprintf(g_msgBuf, "%ld kilobits/sec (%ldK/s)", (lBytesPerSec+124)/125, (lBytesPerSec+1023)/1024);
  2620.                 SetDlgItemText(hDlg, IDC_VIDEO_AVGBITRATE, g_msgBuf);
  2621.             }
  2622.  
  2623.             if (pInfo->lpszAudioMode && thisPtr->audioSrc) {
  2624.                 static const char *szLayers[]={"I","II","III"};
  2625.                 WAVEFORMATEX *fmt = thisPtr->audioSrc->getWaveFormat();
  2626.  
  2627.                 sprintf(g_msgBuf, "%ldKHz %s, %ldkbps layer %s", fmt->nSamplesPerSec/1000, pInfo->lpszAudioMode, pInfo->lAudioAvgBitrate, szLayers[3-((thisPtr->audio_first_header>>9)&3)]);
  2628.                 SetDlgItemText(hDlg, IDC_AUDIO_FORMAT, g_msgBuf);
  2629.  
  2630.                 sprintf(g_msgBuf, "%ldK", (pInfo->lAudioSize + 1023) / 1024);
  2631.                 SetDlgItemText(hDlg, IDC_AUDIO_SIZE, g_msgBuf);
  2632.             }
  2633.  
  2634.             /////////
  2635.  
  2636.             if (pInfo->hWndAbort) {
  2637.                 KillTimer(hDlg, pInfo->statTimer);
  2638.                 return TRUE;
  2639.             }
  2640.  
  2641.             break;
  2642.  
  2643.         case WM_USER+256:
  2644.             EndDialog(hDlg, TRUE);  
  2645.             break;
  2646.     }
  2647.     return FALSE;
  2648. }
  2649.  
  2650. void InputFileMPEG::InfoDialog(HWND hwndParent) {
  2651.     MyFileInfo mai;
  2652.  
  2653.     memset(&mai, 0, sizeof mai);
  2654.     mai.thisPtr = this;
  2655.  
  2656.     DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_MPEG_INFO), hwndParent, _InfoDlgProc, (LPARAM)&mai);
  2657. }
  2658.